• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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