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