HdmiLogger.java revision 2e8f1b6399089626b4f0249427626ba6e63a62ef
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.hdmi; 18 19import android.annotation.Nullable; 20import android.os.SystemClock; 21import android.util.Pair; 22import android.util.Slog; 23 24import java.util.HashMap; 25 26/** 27 * A logger that prevents spammy log. For the same log message, it logs once every 20seconds. 28 * This class is not thread-safe. 29 * <p> 30 * For convenience, use single character prefix for all messages. 31 * Here are common acronyms 32 * <ul> 33 * <li>[T]: Timout 34 * <li>[R]: Received message 35 * <li>[S]: Sent message 36 * <li>[P]: Device polling result 37 * </ul> 38 */ 39final class HdmiLogger { 40 private static final String TAG = "HDMI"; 41 // Logging duration for same error message. 42 private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000; // 20s 43 44 private static final boolean DEBUG = false; 45 46 private static final ThreadLocal<HdmiLogger> sLogger = new ThreadLocal<>(); 47 48 // Key (String): log message. 49 // Value (Pair(Long, Integer)): a pair of last log time millis and the number of logMessage. 50 // Cache for warning. 51 private final HashMap<String, Pair<Long, Integer>> mWarningTimingCache = new HashMap<>(); 52 // Cache for error. 53 private final HashMap<String, Pair<Long, Integer>> mErrorTimingCache = new HashMap<>(); 54 55 private HdmiLogger() { 56 } 57 58 static final void warning(String logMessage, Object... objs) { 59 getLogger().warningInternal(toLogString(logMessage, objs)); 60 } 61 62 private void warningInternal(String logMessage) { 63 String log = updateLog(mWarningTimingCache, logMessage); 64 if (!log.isEmpty()) { 65 Slog.w(TAG, log); 66 } 67 } 68 69 static final void error(String logMessage, Object... objs) { 70 getLogger().errorInternal(toLogString(logMessage, objs)); 71 } 72 73 private void errorInternal(String logMessage) { 74 String log = updateLog(mErrorTimingCache, logMessage); 75 if (!log.isEmpty()) { 76 Slog.e(TAG, log); 77 } 78 } 79 80 static final void debug(String logMessage, Object... objs) { 81 getLogger().debugInternal(toLogString(logMessage, objs)); 82 } 83 84 private void debugInternal(String logMessage) { 85 if (!DEBUG) { 86 return; 87 } 88 Slog.d(TAG, logMessage); 89 } 90 91 private static final String toLogString(String logMessage, Object[] objs) { 92 if (objs.length > 0) { 93 return String.format(logMessage, objs); 94 } else { 95 return logMessage; 96 } 97 } 98 99 private static HdmiLogger getLogger() { 100 HdmiLogger logger = sLogger.get(); 101 if (logger == null) { 102 logger = new HdmiLogger(); 103 sLogger.set(logger); 104 } 105 return logger; 106 } 107 108 private static String updateLog(HashMap<String, Pair<Long, Integer>> cache, String logMessage) { 109 long curTime = SystemClock.uptimeMillis(); 110 Pair<Long, Integer> timing = cache.get(logMessage); 111 if (shouldLogNow(timing, curTime)) { 112 String log = buildMessage(logMessage, timing); 113 cache.put(logMessage, new Pair<>(curTime, 1)); 114 return log; 115 } else { 116 increaseLogCount(cache, logMessage); 117 } 118 return ""; 119 } 120 121 private static String buildMessage(String message, @Nullable Pair<Long, Integer> timing) { 122 return new StringBuilder() 123 .append("[").append(timing == null ? 1 : timing.second).append("]:") 124 .append(message).toString(); 125 } 126 127 private static void increaseLogCount(HashMap<String, Pair<Long, Integer>> cache, 128 String message) { 129 Pair<Long, Integer> timing = cache.get(message); 130 if (timing != null) { 131 cache.put(message, new Pair<>(timing.first, timing.second + 1)); 132 } 133 } 134 135 private static boolean shouldLogNow(@Nullable Pair<Long, Integer> timing, long curTime) { 136 return timing == null || curTime - timing.first > ERROR_LOG_DURATTION_MILLIS; 137 } 138} 139