1 /*
2  * Copyright 2018 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.pump.util;
18 
19 import androidx.annotation.AnyThread;
20 import androidx.annotation.NonNull;
21 
22 import com.android.pump.BuildConfig;
23 
24 import java.util.Locale;
25 import java.util.regex.Pattern;
26 
27 @AnyThread
28 public final class Clog {
29     private static final boolean COLORIZE = BuildConfig.DEBUG;
30 
31     public static final int VERBOSE = android.util.Log.VERBOSE;
32     public static final int DEBUG = android.util.Log.DEBUG;
33     public static final int INFO = android.util.Log.INFO;
34     public static final int WARN = android.util.Log.WARN;
35     public static final int ERROR = android.util.Log.ERROR;
36     public static final int ASSERT = android.util.Log.ASSERT;
37 
38     private static final int COLOR_BLACK = 30;
39     private static final int COLOR_RED = 31;
40     private static final int COLOR_GREEN = 32;
41     private static final int COLOR_YELLOW = 33;
42     private static final int COLOR_BLUE = 34;
43     private static final int COLOR_MAGENTA = 35;
44     private static final int COLOR_CYAN = 36;
45     //private static final int COLOR_WHITE = 37;
46 
47     private static final int MAX_TAG_LENGTH = 23;
48     private static final int MAX_LINE_LENGTH = 1024;
49 
50     private static final Pattern LINE_BREAKER = Pattern.compile("\\r?\\n");
51 
Clog()52     private Clog() { }
53 
tag(@onNull Class<?> clazz)54     public static @NonNull String tag(@NonNull Class<?> clazz) {
55         String tag = clazz.getSimpleName();
56         return tag.substring(0, Math.min(tag.length(), MAX_TAG_LENGTH));
57     }
58 
v(@onNull String tag, @NonNull String msg)59     public static int v(@NonNull String tag, @NonNull String msg) {
60         return println(VERBOSE, tag, msg);
61     }
62 
v(@onNull String tag, @NonNull String msg, @NonNull Throwable tr)63     public static int v(@NonNull String tag, @NonNull String msg, @NonNull Throwable tr) {
64         return println(VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
65     }
66 
d(@onNull String tag, @NonNull String msg)67     public static int d(@NonNull String tag, @NonNull String msg) {
68         return println(DEBUG, tag, msg);
69     }
70 
d(@onNull String tag, @NonNull String msg, @NonNull Throwable tr)71     public static int d(@NonNull String tag, @NonNull String msg, @NonNull Throwable tr) {
72         return println(DEBUG, tag, msg + '\n' + getStackTraceString(tr));
73     }
74 
i(@onNull String tag, @NonNull String msg)75     public static int i(@NonNull String tag, @NonNull String msg) {
76         return println(INFO, tag, msg);
77     }
78 
i(@onNull String tag, @NonNull String msg, @NonNull Throwable tr)79     public static int i(@NonNull String tag, @NonNull String msg, @NonNull Throwable tr) {
80         return println(INFO, tag, msg + '\n' + getStackTraceString(tr));
81     }
82 
w(@onNull String tag, @NonNull String msg)83     public static int w(@NonNull String tag, @NonNull String msg) {
84         return println(WARN, tag, msg);
85     }
86 
w(@onNull String tag, @NonNull String msg, @NonNull Throwable tr)87     public static int w(@NonNull String tag, @NonNull String msg, @NonNull Throwable tr) {
88         return println(WARN, tag, msg + '\n' + getStackTraceString(tr));
89     }
90 
isLoggable(@onNull String tag, int level)91     public static boolean isLoggable(@NonNull String tag, int level) {
92         return android.util.Log.isLoggable(tag, level);
93     }
94 
w(@onNull String tag, @NonNull Throwable tr)95     public static int w(@NonNull String tag, @NonNull Throwable tr) {
96         return println(WARN, tag, getStackTraceString(tr));
97     }
98 
e(@onNull String tag, @NonNull String msg)99     public static int e(@NonNull String tag, @NonNull String msg) {
100         return println(ERROR, tag, msg);
101     }
102 
e(@onNull String tag, @NonNull String msg, @NonNull Throwable tr)103     public static int e(@NonNull String tag, @NonNull String msg, @NonNull Throwable tr) {
104         return println(ERROR, tag, msg + '\n' + getStackTraceString(tr));
105     }
106 
wtf(@onNull String tag, @NonNull String msg)107     public static int wtf(@NonNull String tag, @NonNull String msg) {
108         return android.util.Log.wtf(tag, msg);
109     }
110 
wtf(@onNull String tag, @NonNull Throwable tr)111     public static int wtf(@NonNull String tag, @NonNull Throwable tr) {
112         return android.util.Log.wtf(tag, tr);
113     }
114 
wtf(@onNull String tag, @NonNull String msg, @NonNull Throwable tr)115     public static int wtf(@NonNull String tag, @NonNull String msg, @NonNull Throwable tr) {
116         return android.util.Log.wtf(tag, msg, tr);
117     }
118 
getStackTraceString(@onNull Throwable tr)119     public static @NonNull String getStackTraceString(@NonNull Throwable tr) {
120         return android.util.Log.getStackTraceString(tr);
121     }
122 
println(int priority, @NonNull String tag, @NonNull String msg)123     public static int println(int priority, @NonNull String tag, @NonNull String msg) {
124         tag = String.valueOf(tag);
125         msg = String.valueOf(msg);
126 
127         int color;
128         switch (priority) {
129             case VERBOSE:
130                 color = COLOR_CYAN;
131                 break;
132             case DEBUG:
133                 color = COLOR_BLUE;
134                 break;
135             case INFO:
136                 color = COLOR_GREEN;
137                 break;
138             case WARN:
139                 color = COLOR_YELLOW;
140                 break;
141             case ERROR:
142                 color = COLOR_RED;
143                 break;
144             case ASSERT:
145                 color = COLOR_MAGENTA;
146                 break;
147             default:
148                 color = COLOR_BLACK;
149                 break;
150         }
151 
152         int result = 0;
153         for (String line : LINE_BREAKER.split(msg)) {
154             int length = line.length();
155             for (int start = 0; start < length; start += MAX_LINE_LENGTH) {
156                 String part = line.substring(start, Math.min(start + MAX_LINE_LENGTH, length));
157                 result += android.util.Log.println(priority, tag, colorize(part, color));
158             }
159         }
160         return result;
161     }
162 
colorize(String msg, int color)163     private static String colorize(String msg, int color) {
164         if (COLORIZE) {
165             return String.format(Locale.ROOT, "\033[%2$dm%1$s\033[0m", msg, color);
166         }
167         return msg;
168     }
169 }
170