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>Like the other logging classes, e.g. {@link Log} and {@link Slog}, the
34  * methods in this class log unconditionally regardless of {@link Log#isLoggable(String, int)}.
35  * Therefore, these methods exist just for the convenience of handling formatting.  (Even if they
36  * did check {@link Log#isLoggable(String, int)} before formatting and logging, calling a varargs
37  * method in Java still involves an array allocation.)  If you need to avoid the overhead of logging
38  * on a performance-critical path, either don't use logging in that place, or make the logging
39  * conditional on a static boolean defaulting to false.
40  */
41 public final class Slogf {
42 
43     @GuardedBy("sMessageBuilder")
44     private static final StringBuilder sMessageBuilder;
45 
46     @GuardedBy("sMessageBuilder")
47     private static final Formatter sFormatter;
48 
49     static {
50         TimingsTraceLog t = new TimingsTraceLog("SLog", Trace.TRACE_TAG_SYSTEM_SERVER);
51         t.traceBegin("static_init");
52         sMessageBuilder = new StringBuilder();
53         sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
t.traceEnd()54         t.traceEnd();
55     }
56 
Slogf()57     private Slogf() {
58         throw new UnsupportedOperationException("provides only static methods");
59     }
60 
61     /** Same as {@link Slog#v(String, String)}. */
v(String tag, String msg)62     public static int v(String tag, String msg) {
63         return Slog.v(tag, msg);
64     }
65 
66     /** Same as {@link Slog#v(String, String, Throwable)}. */
v(String tag, String msg, Throwable tr)67     public static int v(String tag, String msg, Throwable tr) {
68         return Slog.v(tag, msg, tr);
69     }
70 
71     /** Same as {@link Slog#d(String, String)}. */
d(String tag, String msg)72     public static int d(String tag, String msg) {
73         return Slog.d(tag, msg);
74     }
75 
76     /** Same as {@link Slog#d(String, String, Throwable)}. */
d(String tag, String msg, Throwable tr)77     public static int d(String tag, String msg, Throwable tr) {
78         return Slog.d(tag, msg, tr);
79     }
80 
81     /** Same as {@link Slog#i(String, String)}. */
i(String tag, String msg)82     public static int i(String tag, String msg) {
83         return Slog.i(tag, msg);
84     }
85 
86     /** Same as {@link Slog#i(String, String, Throwable)}. */
i(String tag, String msg, Throwable tr)87     public static int i(String tag, String msg, Throwable tr) {
88         return Slog.i(tag, msg, tr);
89     }
90 
91     /** Same as {@link Slog#w(String, String)}. */
w(String tag, String msg)92     public static int w(String tag, String msg) {
93         return Slog.w(tag, msg);
94     }
95 
96     /** Same as {@link Slog#w(String, String, Throwable)}. */
w(String tag, String msg, Throwable tr)97     public static int w(String tag, String msg, Throwable tr) {
98         return Slog.w(tag, msg, tr);
99     }
100 
101     /** Same as {@link Slog#w(String, String)}. */
w(String tag, Throwable tr)102     public static int w(String tag, Throwable tr) {
103         return Slog.w(tag, tr);
104     }
105 
106     /** Same as {@link Slog#e(String, String)}. */
e(String tag, String msg)107     public static int e(String tag, String msg) {
108         return Slog.e(tag, msg);
109     }
110 
111     /** Same as {@link Slog#e(String, String, Throwable)}. */
e(String tag, String msg, Throwable tr)112     public static int e(String tag, String msg, Throwable tr) {
113         return Slog.e(tag, msg, tr);
114     }
115 
116     /** Same as {@link Slog#wtf(String, String)}. */
wtf(String tag, String msg)117     public static int wtf(String tag, String msg) {
118         return Slog.wtf(tag, msg);
119     }
120 
121     /** Same as {@link Slog#wtfQuiet(String, String)}. */
wtfQuiet(String tag, String msg)122     public static void wtfQuiet(String tag, String msg) {
123         Slog.wtfQuiet(tag, msg);
124     }
125 
126     /** Same as {@link Slog#wtfStack(String, String). */
wtfStack(String tag, String msg)127     public static int wtfStack(String tag, String msg) {
128         return Slog.wtfStack(tag, msg);
129     }
130 
131     /** Same as {@link Slog#wtf(String, Throwable). */
wtf(String tag, Throwable tr)132     public static int wtf(String tag, Throwable tr) {
133         return Slog.wtf(tag, tr);
134     }
135 
136     /** Same as {@link Slog#wtf(String, String, Throwable)}. */
wtf(String tag, String msg, Throwable tr)137     public static int wtf(String tag, String msg, Throwable tr) {
138         return Slog.wtf(tag, msg, tr);
139     }
140 
141     /** Same as {@link Slog#println(int, String, String)}. */
println(int priority, String tag, String msg)142     public static int println(int priority, String tag, String msg) {
143         return Slog.println(priority, tag, msg);
144     }
145 
146     /** Logs a {@link Log.VERBOSE} message. */
v(String tag, String format, @Nullable Object... args)147     public static void v(String tag, String format, @Nullable Object... args) {
148         v(tag, getMessage(format, args));
149     }
150 
151     /** Logs a {@link Log.VERBOSE} message with a throwable. */
v(String tag, Throwable throwable, String format, @Nullable Object... args)152     public static void v(String tag, Throwable throwable, String format, @Nullable Object... args) {
153         v(tag, getMessage(format, args), throwable);
154     }
155 
156     /** Logs a {@link Log.DEBUG} message. */
d(String tag, String format, @Nullable Object... args)157     public static void d(String tag, String format, @Nullable Object... args) {
158         d(tag, getMessage(format, args));
159     }
160 
161     /** Logs a {@link Log.DEBUG} message with a throwable. */
d(String tag, Throwable throwable, String format, @Nullable Object... args)162     public static void d(String tag, Throwable throwable, String format, @Nullable Object... args) {
163         d(tag, getMessage(format, args), throwable);
164     }
165 
166     /** Logs a {@link Log.INFO} message. */
i(String tag, String format, @Nullable Object... args)167     public static void i(String tag, String format, @Nullable Object... args) {
168         i(tag, getMessage(format, args));
169     }
170 
171     /** Logs a {@link Log.INFO} message with a throwable. */
i(String tag, Throwable throwable, String format, @Nullable Object... args)172     public static void i(String tag, Throwable throwable, String format, @Nullable Object... args) {
173         i(tag, getMessage(format, args), throwable);
174     }
175 
176     /** Logs a {@link Log.WARN} message. */
w(String tag, String format, @Nullable Object... args)177     public static void w(String tag, String format, @Nullable Object... args) {
178         w(tag, getMessage(format, args));
179     }
180 
181     /** Logs a {@link Log.WARN} message with a throwable. */
w(String tag, Throwable throwable, String format, @Nullable Object... args)182     public static void w(String tag, Throwable throwable, String format, @Nullable Object... args) {
183         w(tag, getMessage(format, args), throwable);
184     }
185 
186     /** Logs a {@link Log.ERROR} message. */
e(String tag, String format, @Nullable Object... args)187     public static void e(String tag, String format, @Nullable Object... args) {
188         e(tag, getMessage(format, args));
189     }
190 
191     /** Logs a {@link Log.ERROR} message with a throwable. */
e(String tag, Throwable throwable, String format, @Nullable Object... args)192     public static void e(String tag, Throwable throwable, String format, @Nullable Object... args) {
193         e(tag, getMessage(format, args), throwable);
194     }
195 
196     /** Logs a {@code wtf} message. */
wtf(String tag, String format, @Nullable Object... args)197     public static void wtf(String tag, String format, @Nullable Object... args) {
198         wtf(tag, getMessage(format, args));
199     }
200 
201     /** Logs a {@code wtf} message with a throwable. */
wtf(String tag, Throwable throwable, String format, @Nullable Object... args)202     public static void wtf(String tag, Throwable throwable, String format,
203             @Nullable Object... args) {
204         wtf(tag, getMessage(format, args), throwable);
205     }
206 
getMessage(String format, @Nullable Object... args)207     private static String getMessage(String format, @Nullable Object... args) {
208         synchronized (sMessageBuilder) {
209             sFormatter.format(format, args);
210             String message = sMessageBuilder.toString();
211             sMessageBuilder.setLength(0);
212             return message;
213         }
214     }
215 }
216