• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
19 
20 // This is the client API for the typed logger.
21 
22 #include <media/nblog/NBLog.h>
23 #include <algorithm>
24 
25 /*
26 Fowler-Noll-Vo (FNV-1a) hash function for the file name.
27 Hashes at compile time. FNV-1a iterative function:
28 
29 hash = offset_basis
30 for each byte to be hashed
31         hash = hash xor byte
32         hash = hash * FNV_prime
33 return hash
34 
35 offset_basis and FNV_prime values depend on the size of the hash output
36 Following values are defined by FNV and should not be changed arbitrarily
37 */
38 
39 template<typename T>
40 constexpr T offset_basis();
41 
42 template<typename T>
43 constexpr T FNV_prime();
44 
45 template<>
46 constexpr uint32_t offset_basis<uint32_t>() {
47     return 2166136261u;
48 }
49 
50 template<>
51 constexpr uint32_t FNV_prime<uint32_t>() {
52     return 16777619u;
53 }
54 
55 template<>
56 constexpr uint64_t offset_basis<uint64_t>() {
57     return 14695981039346656037ull;
58 }
59 
60 template<>
61 constexpr uint64_t FNV_prime<uint64_t>() {
62     return 1099511628211ull;
63 }
64 
65 template <typename T, size_t n>
66 __attribute__((no_sanitize("unsigned-integer-overflow")))
67 constexpr T fnv1a(const char (&file)[n], ssize_t i = (ssize_t)n - 1) {
68     return i == -1 ? offset_basis<T>() : (fnv1a<T>(file, i - 1) ^ file[i]) * FNV_prime<T>();
69 }
70 
71 template <size_t n>
hash(const char (& file)[n],uint32_t line)72 constexpr uint64_t hash(const char (&file)[n], uint32_t line) {
73     // Line numbers over or equal to 2^16 are clamped to 2^16 - 1. This way increases collisions
74     // compared to wrapping around, but is easy to identify because it doesn't produce aliasing.
75     // It's a very unlikely case anyways.
76     return ((fnv1a<uint64_t>(file) << 16) ^ ((fnv1a<uint64_t>(file) >> 32) & 0xFFFF0000)) |
77            std::min(line, 0xFFFFu);
78 }
79 
80 // TODO Permit disabling of logging at compile-time.
81 
82 // TODO A non-nullptr stub implementation that is a nop would be faster than checking for nullptr
83 //      in the case when logging is enabled at compile-time and enabled at runtime, but it might be
84 //      slower than nullptr check when logging is enabled at compile-time and disabled at runtime.
85 
86 // Write formatted entry to log
87 #define LOGT(fmt, ...) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
88                                 x->logFormat((fmt), hash(__FILE__, __LINE__), ##__VA_ARGS__); } \
89                                 while (0)
90 
91 // Write histogram timestamp entry
92 #define LOG_HIST_TS() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
93         x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
94 
95 // Record that audio was turned on/off
96 #define LOG_AUDIO_STATE() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
97         x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
98 
99 // Log the difference bewteen frames presented by HAL and frames written to HAL output sink,
100 // divided by the sample rate. Parameter ms is of type double.
101 #define LOG_LATENCY(ms) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
102         x->log<NBLog::EVENT_LATENCY>(ms); } while (0)
103 
104 // Record thread overrun event nanosecond timestamp. Parameter ns is an int64_t.
105 #define LOG_OVERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
106         x->log<NBLog::EVENT_OVERRUN>(ns); } while (0)
107 
108 // Record thread info. This currently includes type, frameCount, and sampleRate.
109 // Parameter type is thread_info_t as defined in NBLog.h.
110 #define LOG_THREAD_INFO(info) do { NBLog::Writer *x = aflog::getThreadWriter(); \
111         if (x != nullptr) x->log<NBLog::EVENT_THREAD_INFO>(info); } while (0)
112 
113 #define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = aflog::getThreadWriter(); \
114         if (x != nullptr) x->log<NBLog::EVENT_THREAD_PARAMS>(params); } while (0)
115 
116 // Record thread underrun event nanosecond timestamp. Parameter ns is an int64_t.
117 #define LOG_UNDERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
118         x->log<NBLog::EVENT_UNDERRUN>(ns); } while (0)
119 
120 // Record thread warmup time in milliseconds. Parameter ms is of type double.
121 #define LOG_WARMUP_TIME(ms) do { \
122         NBLog::Writer *x = aflog::getThreadWriter(); 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 = aflog::getThreadWriter(); if (x != nullptr) \
128         x->log<NBLog::EVENT_WORK_TIME>(ns); } while (0)
129 
130 namespace android::aflog {
131 // TODO consider adding a thread_local NBLog::Writer tlStubNBLogWriter and then
132 // initialize setThreadWriter() to &tlStubNBLogWriter to remove the need to
133 // check for nullptr every time. Also reduces the need to add a new logging macro above
134 // each time we want to log a new type.
135 
136 NBLog::Writer *getThreadWriter();
137 void setThreadWriter(NBLog::Writer *writer);
138 
139 } // namespace android::aflog
140