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>
hash(const char (& file)[n],uint32_t line)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 namespace android {
101 extern "C" {
102 extern thread_local NBLog::Writer *tlNBLogWriter;
103 }
104 } // namespace android
105 
106 #endif // ANDROID_TYPED_LOGGER_H
107