diff --git a/services/core/java/com/android/server/utils/Slogf.java b/services/core/java/com/android/server/utils/Slogf.java index bbc541438c828..e88ac63615ca2 100644 --- a/services/core/java/com/android/server/utils/Slogf.java +++ b/services/core/java/com/android/server/utils/Slogf.java @@ -161,6 +161,21 @@ public final class Slogf { v(tag, getMessage(format, args)); } + /** + * Logs a {@link Log.VEBOSE} message with an exception + * + *

Note: the message will only be formatted if {@link Log#VERBOSE} logging + * is enabled for the given {@code tag}, but the compiler will still create an intermediate + * array of the objects for the {@code vargars}, which could affect garbage collection. So, if + * you're calling this method in a critical path, make sure to explicitly do the check before + * calling it. + */ + public static void v(String tag, Exception exception, String format, @Nullable Object... args) { + if (!isLoggable(tag, Log.VERBOSE)) return; + + v(tag, getMessage(format, args), exception); + } + /** * Logs a {@link Log.DEBUG} message. * @@ -176,6 +191,21 @@ public final class Slogf { d(tag, getMessage(format, args)); } + /** + * Logs a {@link Log.DEBUG} message with an exception + * + *

Note: the message will only be formatted if {@link Log#DEBUG} logging + * is enabled for the given {@code tag}, but the compiler will still create an intermediate + * array of the objects for the {@code vargars}, which could affect garbage collection. So, if + * you're calling this method in a critical path, make sure to explicitly do the check before + * calling it. + */ + public static void d(String tag, Exception exception, String format, @Nullable Object... args) { + if (!isLoggable(tag, Log.DEBUG)) return; + + d(tag, getMessage(format, args), exception); + } + /** * Logs a {@link Log.INFO} message. * @@ -191,6 +221,21 @@ public final class Slogf { i(tag, getMessage(format, args)); } + /** + * Logs a {@link Log.INFO} message with an exception + * + *

Note: the message will only be formatted if {@link Log#INFO} logging + * is enabled for the given {@code tag}, but the compiler will still create an intermediate + * array of the objects for the {@code vargars}, which could affect garbage collection. So, if + * you're calling this method in a critical path, make sure to explicitly do the check before + * calling it. + */ + public static void i(String tag, Exception exception, String format, @Nullable Object... args) { + if (!isLoggable(tag, Log.INFO)) return; + + i(tag, getMessage(format, args), exception); + } + /** * Logs a {@link Log.WARN} message. * @@ -220,6 +265,7 @@ public final class Slogf { w(tag, getMessage(format, args), exception); } + /** * Logs a {@link Log.ERROR} message. * diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java index 3e8cef9afc152..ae25c1bb3db8b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java @@ -102,6 +102,24 @@ public final class SlogfTest { verify(()-> Slog.v(eq(TAG), any()), never()); } + @Test + public void testV_msgFormattedWithException_enabled() { + enableLogging(Log.VERBOSE); + + Slogf.v(TAG, mException, "msg in a %s", "bottle"); + + verify(()-> Slog.v(TAG, "msg in a bottle", mException)); + } + + @Test + public void testV_msgFormattedWithException_disabled() { + disableLogging(Log.VERBOSE); + + Slogf.v(TAG, "msg in a %s", "bottle"); + + verify(()-> Slog.v(eq(TAG), any(String.class), any(Throwable.class)), never()); + } + @Test public void testD_msg() { Slogf.d(TAG, "msg"); @@ -134,6 +152,24 @@ public final class SlogfTest { verify(()-> Slog.d(eq(TAG), any()), never()); } + @Test + public void testD_msgFormattedWithException_enabled() { + enableLogging(Log.DEBUG); + + Slogf.d(TAG, mException, "msg in a %s", "bottle"); + + verify(()-> Slog.d(TAG, "msg in a bottle", mException)); + } + + @Test + public void testD_msgFormattedWithException_disabled() { + disableLogging(Log.DEBUG); + + Slogf.d(TAG, mException, "msg in a %s", "bottle"); + + verify(()-> Slog.d(eq(TAG), any(String.class), any(Throwable.class)), never()); + } + @Test public void testI_msg() { Slogf.i(TAG, "msg"); @@ -166,6 +202,24 @@ public final class SlogfTest { verify(()-> Slog.i(eq(TAG), any()), never()); } + @Test + public void testI_msgFormattedWithException_enabled() { + enableLogging(Log.INFO); + + Slogf.i(TAG, mException, "msg in a %s", "bottle"); + + verify(()-> Slog.i(TAG, "msg in a bottle", mException)); + } + + @Test + public void testI_msgFormattedWithException_disabled() { + disableLogging(Log.INFO); + + Slogf.i(TAG, mException, "msg in a %s", "bottle"); + + verify(()-> Slog.i(eq(TAG), any(String.class), any(Throwable.class)), never()); + } + @Test public void testW_msg() { Slogf.w(TAG, "msg"); @@ -218,7 +272,7 @@ public final class SlogfTest { public void testW_msgFormattedWithException_disabled() { disableLogging(Log.WARN); - Slogf.w(TAG, "msg in a %s", "bottle"); + Slogf.w(TAG, mException, "msg in a %s", "bottle"); verify(()-> Slog.w(eq(TAG), any(String.class), any(Throwable.class)), never()); } @@ -268,7 +322,7 @@ public final class SlogfTest { public void testE_msgFormattedWithException_disabled() { disableLogging(Log.ERROR); - Slogf.e(TAG, "msg in a %s", "bottle"); + Slogf.e(TAG, mException, "msg in a %s", "bottle"); verify(()-> Slog.e(eq(TAG), any(String.class), any(Throwable.class)), never()); }