Home | History | Annotate | Download | only in audioflinger
      1 /*
      2  *
      3  * Copyright 2017, The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #ifndef ANDROID_TYPED_LOGGER_H
     19 #define ANDROID_TYPED_LOGGER_H
     20 
     21 // This is the client API for the typed logger.
     22 
     23 #include <media/nblog/NBLog.h>
     24 #include <algorithm>
     25 
     26 /*
     27 Fowler-Noll-Vo (FNV-1a) hash function for the file name.
     28 Hashes at compile time. FNV-1a iterative function:
     29 
     30 hash = offset_basis
     31 for each byte to be hashed
     32         hash = hash xor byte
     33         hash = hash * FNV_prime
     34 return hash
     35 
     36 offset_basis and FNV_prime values depend on the size of the hash output
     37 Following values are defined by FNV and should not be changed arbitrarily
     38 */
     39 
     40 template<typename T>
     41 constexpr T offset_basis();
     42 
     43 template<typename T>
     44 constexpr T FNV_prime();
     45 
     46 template<>
     47 constexpr uint32_t offset_basis<uint32_t>() {
     48     return 2166136261u;
     49 }
     50 
     51 template<>
     52 constexpr uint32_t FNV_prime<uint32_t>() {
     53     return 16777619u;
     54 }
     55 
     56 template<>
     57 constexpr uint64_t offset_basis<uint64_t>() {
     58     return 14695981039346656037ull;
     59 }
     60 
     61 template<>
     62 constexpr uint64_t FNV_prime<uint64_t>() {
     63     return 1099511628211ull;
     64 }
     65 
     66 template <typename T, size_t n>
     67 __attribute__((no_sanitize("unsigned-integer-overflow")))
     68 constexpr T fnv1a(const char (&file)[n], ssize_t i = (ssize_t)n - 1) {
     69     return i == -1 ? offset_basis<T>() : (fnv1a<T>(file, i - 1) ^ file[i]) * FNV_prime<T>();
     70 }
     71 
     72 template <size_t n>
     73 constexpr uint64_t hash(const char (&file)[n], uint32_t line) {
     74     // Line numbers over or equal to 2^16 are clamped to 2^16 - 1. This way increases collisions
     75     // compared to wrapping around, but is easy to identify because it doesn't produce aliasing.
     76     // It's a very unlikely case anyways.
     77     return ((fnv1a<uint64_t>(file) << 16) ^ ((fnv1a<uint64_t>(file) >> 32) & 0xFFFF0000)) |
     78            std::min(line, 0xFFFFu);
     79 }
     80 
     81 // TODO Permit disabling of logging at compile-time.
     82 
     83 // TODO A non-nullptr dummy implementation that is a nop would be faster than checking for nullptr
     84 //      in the case when logging is enabled at compile-time and enabled at runtime, but it might be
     85 //      slower than nullptr check when logging is enabled at compile-time and disabled at runtime.
     86 
     87 // Write formatted entry to log
     88 #define LOGT(fmt, ...) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
     89                                 x->logFormat((fmt), hash(__FILE__, __LINE__), ##__VA_ARGS__); } \
     90                                 while (0)
     91 
     92 // Write histogram timestamp entry
     93 #define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
     94         x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
     95 
     96 // Record that audio was turned on/off
     97 #define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
     98         x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
     99 
    100 // Log the difference bewteen frames presented by HAL and frames written to HAL output sink,
    101 // divided by the sample rate. Parameter ms is of type double.
    102 #define LOG_LATENCY(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
    103         x->log<NBLog::EVENT_LATENCY>(ms); } while (0)
    104 
    105 // Record thread overrun event nanosecond timestamp. Parameter ns is an int64_t.
    106 #define LOG_OVERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
    107         x->log<NBLog::EVENT_OVERRUN>(ns); } while (0)
    108 
    109 // Record thread info. This currently includes type, frameCount, and sampleRate.
    110 // Parameter type is thread_info_t as defined in NBLog.h.
    111 #define LOG_THREAD_INFO(info) do { NBLog::Writer *x = tlNBLogWriter; \
    112         if (x != nullptr) x->log<NBLog::EVENT_THREAD_INFO>(info); } while (0)
    113 
    114 #define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = tlNBLogWriter; \
    115         if (x != nullptr) x->log<NBLog::EVENT_THREAD_PARAMS>(params); } while (0)
    116 
    117 // Record thread underrun event nanosecond timestamp. Parameter ns is an int64_t.
    118 #define LOG_UNDERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
    119         x->log<NBLog::EVENT_UNDERRUN>(ns); } while (0)
    120 
    121 // Record thread warmup time in milliseconds. Parameter ms is of type double.
    122 #define LOG_WARMUP_TIME(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
    123         x->log<NBLog::EVENT_WARMUP_TIME>(ms); } while (0)
    124 
    125 // Record a typed entry that represents a thread's work time in nanoseconds.
    126 // Parameter ns should be of type uint32_t.
    127 #define LOG_WORK_TIME(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
    128         x->log<NBLog::EVENT_WORK_TIME>(ns); } while (0)
    129 
    130 namespace android {
    131 extern "C" {
    132 // TODO consider adding a thread_local NBLog::Writer tlDummyNBLogWriter and then
    133 // initialize below tlNBLogWriter to &tlDummyNBLogWriter to remove the need to
    134 // check for nullptr every time. Also reduces the need to add a new logging macro above
    135 // each time we want to log a new type.
    136 extern thread_local NBLog::Writer *tlNBLogWriter;
    137 }
    138 } // namespace android
    139 
    140 #endif // ANDROID_TYPED_LOGGER_H
    141