1 /*
2  * Copyright (C) 2020 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.wm.shell.protolog;
18 
19 import android.annotation.Nullable;
20 
21 import com.android.internal.protolog.BaseProtoLogImpl;
22 import com.android.internal.protolog.ProtoLogViewerConfigReader;
23 import com.android.internal.protolog.common.IProtoLogGroup;
24 
25 import java.io.File;
26 import java.io.PrintWriter;
27 
28 
29 /**
30  * A service for the ProtoLog logging system.
31  */
32 public class ShellProtoLogImpl extends BaseProtoLogImpl {
33     private static final String TAG = "ProtoLogImpl";
34     private static final int BUFFER_CAPACITY = 1024 * 1024;
35     // TODO: find a proper location to save the protolog message file
36     private static final String LOG_FILENAME = "/data/misc/wmtrace/shell_log.winscope";
37     private static final String VIEWER_CONFIG_FILENAME = "/system_ext/etc/wmshell.protolog.json.gz";
38 
39     private static ShellProtoLogImpl sServiceInstance = null;
40 
41     static {
ShellProtoLogGroup.values()42         addLogGroupEnum(ShellProtoLogGroup.values());
43     }
44 
45     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
d(IProtoLogGroup group, int messageHash, int paramsMask, @Nullable String messageString, Object... args)46     public static void d(IProtoLogGroup group, int messageHash, int paramsMask,
47             @Nullable String messageString,
48             Object... args) {
49         getSingleInstance()
50                 .log(LogLevel.DEBUG, group, messageHash, paramsMask, messageString, args);
51     }
52 
53     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
v(IProtoLogGroup group, int messageHash, int paramsMask, @Nullable String messageString, Object... args)54     public static void v(IProtoLogGroup group, int messageHash, int paramsMask,
55             @Nullable String messageString,
56             Object... args) {
57         getSingleInstance().log(LogLevel.VERBOSE, group, messageHash, paramsMask, messageString,
58                 args);
59     }
60 
61     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
i(IProtoLogGroup group, int messageHash, int paramsMask, @Nullable String messageString, Object... args)62     public static void i(IProtoLogGroup group, int messageHash, int paramsMask,
63             @Nullable String messageString,
64             Object... args) {
65         getSingleInstance().log(LogLevel.INFO, group, messageHash, paramsMask, messageString, args);
66     }
67 
68     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
w(IProtoLogGroup group, int messageHash, int paramsMask, @Nullable String messageString, Object... args)69     public static void w(IProtoLogGroup group, int messageHash, int paramsMask,
70             @Nullable String messageString,
71             Object... args) {
72         getSingleInstance().log(LogLevel.WARN, group, messageHash, paramsMask, messageString, args);
73     }
74 
75     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
e(IProtoLogGroup group, int messageHash, int paramsMask, @Nullable String messageString, Object... args)76     public static void e(IProtoLogGroup group, int messageHash, int paramsMask,
77             @Nullable String messageString,
78             Object... args) {
79         getSingleInstance()
80                 .log(LogLevel.ERROR, group, messageHash, paramsMask, messageString, args);
81     }
82 
83     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
wtf(IProtoLogGroup group, int messageHash, int paramsMask, @Nullable String messageString, Object... args)84     public static void wtf(IProtoLogGroup group, int messageHash, int paramsMask,
85             @Nullable String messageString,
86             Object... args) {
87         getSingleInstance().log(LogLevel.WTF, group, messageHash, paramsMask, messageString, args);
88     }
89 
90     /** Returns true iff logging is enabled for the given {@code IProtoLogGroup}. */
isEnabled(IProtoLogGroup group)91     public static boolean isEnabled(IProtoLogGroup group) {
92         return group.isLogToLogcat()
93                 || (group.isLogToProto() && getSingleInstance().isProtoEnabled());
94     }
95 
96     /**
97      * Returns the single instance of the ProtoLogImpl singleton class.
98      */
getSingleInstance()99     public static synchronized ShellProtoLogImpl getSingleInstance() {
100         if (sServiceInstance == null) {
101             sServiceInstance = new ShellProtoLogImpl();
102         }
103         return sServiceInstance;
104     }
105 
startTextLogging(String[] groups, PrintWriter pw)106     public int startTextLogging(String[] groups, PrintWriter pw) {
107         mViewerConfig.loadViewerConfig(pw, VIEWER_CONFIG_FILENAME);
108         return setLogging(true /* setTextLogging */, true, pw, groups);
109     }
110 
stopTextLogging(String[] groups, PrintWriter pw)111     public int stopTextLogging(String[] groups, PrintWriter pw) {
112         return setLogging(true /* setTextLogging */, false, pw, groups);
113     }
114 
ShellProtoLogImpl()115     private ShellProtoLogImpl() {
116         super(new File(LOG_FILENAME), VIEWER_CONFIG_FILENAME, BUFFER_CAPACITY,
117                 new ProtoLogViewerConfigReader());
118     }
119 }
120 
121