1 /* 2 * Copyright (C) 2021 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 17 package com.android.server.utils; 18 19 import android.annotation.Nullable; 20 import android.os.Trace; 21 import android.util.Log; 22 import android.util.Slog; 23 import android.util.TimingsTraceLog; 24 25 import com.android.internal.annotations.GuardedBy; 26 27 import java.util.Formatter; 28 import java.util.Locale; 29 30 /** 31 * Extends {@link Slog} by providing overloaded methods that take string formatting. 32 * 33 * <p><strong>Note: </strong>the overloaded methods won't create the formatted message if the 34 * respective logging level is disabled for the tag, but the compiler will still create an 35 * intermediate array of the objects for the {@code vargars}, which could affect garbage collection. 36 * So, if you're calling these method in a critical path, make sure to explicitly check for the 37 * level before calling them. 38 */ 39 public final class Slogf { 40 41 @GuardedBy("sMessageBuilder") 42 private static final StringBuilder sMessageBuilder; 43 44 @GuardedBy("sMessageBuilder") 45 private static final Formatter sFormatter; 46 47 static { 48 TimingsTraceLog t = new TimingsTraceLog("SLog", Trace.TRACE_TAG_SYSTEM_SERVER); 49 t.traceBegin("static_init"); 50 sMessageBuilder = new StringBuilder(); 51 sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH); t.traceEnd()52 t.traceEnd(); 53 } 54 Slogf()55 private Slogf() { 56 throw new UnsupportedOperationException("provides only static methods"); 57 } 58 59 /** Same as {@link Log#isLoggable(String, int)}. */ isLoggable(String tag, int level)60 public static boolean isLoggable(String tag, int level) { 61 return Log.isLoggable(tag, level); 62 } 63 64 /** Same as {@link Slog#v(String, String)}. */ v(String tag, String msg)65 public static int v(String tag, String msg) { 66 return Slog.v(tag, msg); 67 } 68 69 /** Same as {@link Slog#v(String, String, Throwable)}. */ v(String tag, String msg, Throwable tr)70 public static int v(String tag, String msg, Throwable tr) { 71 return Slog.v(tag, msg, tr); 72 } 73 74 /** Same as {@link Slog#d(String, String)}. */ d(String tag, String msg)75 public static int d(String tag, String msg) { 76 return Slog.d(tag, msg); 77 } 78 79 /** Same as {@link Slog#d(String, String, Throwable)}. */ d(String tag, String msg, Throwable tr)80 public static int d(String tag, String msg, Throwable tr) { 81 return Slog.d(tag, msg, tr); 82 } 83 84 /** Same as {@link Slog#i(String, String)}. */ i(String tag, String msg)85 public static int i(String tag, String msg) { 86 return Slog.i(tag, msg); 87 } 88 89 /** Same as {@link Slog#i(String, String, Throwable)}. */ i(String tag, String msg, Throwable tr)90 public static int i(String tag, String msg, Throwable tr) { 91 return Slog.i(tag, msg, tr); 92 } 93 94 /** Same as {@link Slog#w(String, String)}. */ w(String tag, String msg)95 public static int w(String tag, String msg) { 96 return Slog.w(tag, msg); 97 } 98 99 /** Same as {@link Slog#w(String, String, Throwable)}. */ w(String tag, String msg, Throwable tr)100 public static int w(String tag, String msg, Throwable tr) { 101 return Slog.w(tag, msg, tr); 102 } 103 104 /** Same as {@link Slog#w(String, String)}. */ w(String tag, Throwable tr)105 public static int w(String tag, Throwable tr) { 106 return Slog.w(tag, tr); 107 } 108 109 /** Same as {@link Slog#e(String, String)}. */ e(String tag, String msg)110 public static int e(String tag, String msg) { 111 return Slog.e(tag, msg); 112 } 113 114 /** Same as {@link Slog#e(String, String, Throwable)}. */ e(String tag, String msg, Throwable tr)115 public static int e(String tag, String msg, Throwable tr) { 116 return Slog.e(tag, msg, tr); 117 } 118 119 /** Same as {@link Slog#wtf(String, String)}. */ wtf(String tag, String msg)120 public static int wtf(String tag, String msg) { 121 return Slog.wtf(tag, msg); 122 } 123 124 /** Same as {@link Slog#wtfQuiet(String, String)}. */ wtfQuiet(String tag, String msg)125 public static void wtfQuiet(String tag, String msg) { 126 Slog.wtfQuiet(tag, msg); 127 } 128 129 /** Same as {@link Slog#wtfStack(String, String). */ wtfStack(String tag, String msg)130 public static int wtfStack(String tag, String msg) { 131 return Slog.wtfStack(tag, msg); 132 } 133 134 /** Same as {@link Slog#wtf(String, Throwable). */ wtf(String tag, Throwable tr)135 public static int wtf(String tag, Throwable tr) { 136 return Slog.wtf(tag, tr); 137 } 138 139 /** Same as {@link Slog#wtf(String, String, Throwable)}. */ wtf(String tag, String msg, Throwable tr)140 public static int wtf(String tag, String msg, Throwable tr) { 141 return Slog.wtf(tag, msg, tr); 142 } 143 144 /** Same as {@link Slog#println(int, String, String)}. */ println(int priority, String tag, String msg)145 public static int println(int priority, String tag, String msg) { 146 return Slog.println(priority, tag, msg); 147 } 148 149 /** 150 * Logs a {@link Log.VERBOSE} message. 151 * 152 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#VERBOSE} logging 153 * is enabled for the given {@code tag}, but the compiler will still create an intermediate 154 * array of the objects for the {@code vargars}, which could affect garbage collection. So, if 155 * you're calling this method in a critical path, make sure to explicitly do the check before 156 * calling it. 157 */ v(String tag, String format, @Nullable Object... args)158 public static void v(String tag, String format, @Nullable Object... args) { 159 if (!isLoggable(tag, Log.VERBOSE)) return; 160 161 v(tag, getMessage(format, args)); 162 } 163 164 /** 165 * Logs a {@link Log.DEBUG} message. 166 * 167 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#DEBUG} logging is 168 * enabled for the given {@code tag}, but the compiler will still create an intermediate array 169 * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're 170 * calling this method in a critical path, make sure to explicitly do the check before calling 171 * it. 172 */ d(String tag, String format, @Nullable Object... args)173 public static void d(String tag, String format, @Nullable Object... args) { 174 if (!isLoggable(tag, Log.DEBUG)) return; 175 176 d(tag, getMessage(format, args)); 177 } 178 179 /** 180 * Logs a {@link Log.INFO} message. 181 * 182 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#INFO} logging is 183 * enabled for the given {@code tag}, but the compiler will still create an intermediate array 184 * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're 185 * calling this method in a critical path, make sure to explicitly do the check before calling 186 * it. 187 */ i(String tag, String format, @Nullable Object... args)188 public static void i(String tag, String format, @Nullable Object... args) { 189 if (!isLoggable(tag, Log.INFO)) return; 190 191 i(tag, getMessage(format, args)); 192 } 193 194 /** 195 * Logs a {@link Log.WARN} message. 196 * 197 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#WARN} logging is 198 * enabled for the given {@code tag}, but the compiler will still create an intermediate array 199 * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're 200 * calling this method in a critical path, make sure to explicitly do the check before calling 201 * it. 202 */ w(String tag, String format, @Nullable Object... args)203 public static void w(String tag, String format, @Nullable Object... args) { 204 if (!isLoggable(tag, Log.WARN)) return; 205 206 w(tag, getMessage(format, args)); 207 } 208 209 /** 210 * Logs a {@link Log.WARN} message with an exception 211 * 212 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#WARN} logging is 213 * enabled for the given {@code tag}, but the compiler will still create an intermediate array 214 * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're 215 * calling this method in a critical path, make sure to explicitly do the check before calling 216 * it. 217 */ w(String tag, Exception exception, String format, @Nullable Object... args)218 public static void w(String tag, Exception exception, String format, @Nullable Object... args) { 219 if (!isLoggable(tag, Log.WARN)) return; 220 221 w(tag, getMessage(format, args), exception); 222 } 223 /** 224 * Logs a {@link Log.ERROR} message. 225 * 226 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#ERROR} logging is 227 * enabled for the given {@code tag}, but the compiler will still create an intermediate array 228 * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're 229 * calling this method in a critical path, make sure to explicitly do the check before calling 230 * it. 231 */ e(String tag, String format, @Nullable Object... args)232 public static void e(String tag, String format, @Nullable Object... args) { 233 if (!isLoggable(tag, Log.ERROR)) return; 234 235 e(tag, getMessage(format, args)); 236 } 237 238 /** 239 * Logs a {@link Log.ERROR} message with an exception 240 * 241 * <p><strong>Note: </strong>the message will only be formatted if {@link Log#ERROR} logging is 242 * enabled for the given {@code tag}, but the compiler will still create an intermediate array 243 * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're 244 * calling this method in a critical path, make sure to explicitly do the check before calling 245 * it. 246 */ e(String tag, Exception exception, String format, @Nullable Object... args)247 public static void e(String tag, Exception exception, String format, @Nullable Object... args) { 248 if (!isLoggable(tag, Log.ERROR)) return; 249 250 e(tag, getMessage(format, args), exception); 251 } 252 253 /** 254 * Logs a {@code wtf} message. 255 */ wtf(String tag, String format, @Nullable Object... args)256 public static void wtf(String tag, String format, @Nullable Object... args) { 257 wtf(tag, getMessage(format, args)); 258 } 259 260 /** 261 * Logs a {@code wtf} message with an exception. 262 */ wtf(String tag, Exception exception, String format, @Nullable Object... args)263 public static void wtf(String tag, Exception exception, String format, 264 @Nullable Object... args) { 265 wtf(tag, getMessage(format, args), exception); 266 } 267 getMessage(String format, @Nullable Object... args)268 private static String getMessage(String format, @Nullable Object... args) { 269 synchronized (sMessageBuilder) { 270 sFormatter.format(format, args); 271 String message = sMessageBuilder.toString(); 272 sMessageBuilder.setLength(0); 273 return message; 274 } 275 } 276 } 277