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