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 import android.content.Context;
21 import android.util.Log;
22 
23 import com.android.internal.annotations.VisibleForTesting;
24 import com.android.internal.protolog.BaseProtoLogImpl;
25 import com.android.internal.protolog.ProtoLogViewerConfigReader;
26 import com.android.internal.protolog.common.IProtoLogGroup;
27 import com.android.wm.shell.R;
28 
29 import java.io.File;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.PrintWriter;
33 
34 import org.json.JSONException;
35 
36 
37 /**
38  * A service for the ProtoLog logging system.
39  */
40 public class ShellProtoLogImpl extends BaseProtoLogImpl {
41     private static final String TAG = "ProtoLogImpl";
42     private static final int BUFFER_CAPACITY = 1024 * 1024;
43     // TODO: Get the right path for the proto log file when we initialize the shell components
44     private static final String LOG_FILENAME = new File("wm_shell_log.pb").getAbsolutePath();
45 
46     private static ShellProtoLogImpl sServiceInstance = null;
47 
48     static {
ShellProtoLogGroup.values()49         addLogGroupEnum(ShellProtoLogGroup.values());
50     }
51 
52     /** 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)53     public static void d(IProtoLogGroup group, int messageHash, int paramsMask,
54             @Nullable String messageString,
55             Object... args) {
56         getSingleInstance()
57                 .log(LogLevel.DEBUG, group, messageHash, paramsMask, messageString, args);
58     }
59 
60     /** 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)61     public static void v(IProtoLogGroup group, int messageHash, int paramsMask,
62             @Nullable String messageString,
63             Object... args) {
64         getSingleInstance().log(LogLevel.VERBOSE, group, messageHash, paramsMask, messageString,
65                 args);
66     }
67 
68     /** 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)69     public static void i(IProtoLogGroup group, int messageHash, int paramsMask,
70             @Nullable String messageString,
71             Object... args) {
72         getSingleInstance().log(LogLevel.INFO, group, messageHash, paramsMask, messageString, args);
73     }
74 
75     /** 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)76     public static void w(IProtoLogGroup group, int messageHash, int paramsMask,
77             @Nullable String messageString,
78             Object... args) {
79         getSingleInstance().log(LogLevel.WARN, group, messageHash, paramsMask, messageString, args);
80     }
81 
82     /** 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)83     public static void e(IProtoLogGroup group, int messageHash, int paramsMask,
84             @Nullable String messageString,
85             Object... args) {
86         getSingleInstance()
87                 .log(LogLevel.ERROR, group, messageHash, paramsMask, messageString, args);
88     }
89 
90     /** 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)91     public static void wtf(IProtoLogGroup group, int messageHash, int paramsMask,
92             @Nullable String messageString,
93             Object... args) {
94         getSingleInstance().log(LogLevel.WTF, group, messageHash, paramsMask, messageString, args);
95     }
96 
97     /** Returns true iff logging is enabled for the given {@code IProtoLogGroup}. */
isEnabled(IProtoLogGroup group)98     public static boolean isEnabled(IProtoLogGroup group) {
99         return group.isLogToLogcat()
100                 || (group.isLogToProto() && getSingleInstance().isProtoEnabled());
101     }
102 
103     /**
104      * Returns the single instance of the ProtoLogImpl singleton class.
105      */
getSingleInstance()106     public static synchronized ShellProtoLogImpl getSingleInstance() {
107         if (sServiceInstance == null) {
108             sServiceInstance = new ShellProtoLogImpl();
109         }
110         return sServiceInstance;
111     }
112 
startTextLogging(String[] groups, PrintWriter pw)113     public int startTextLogging(String[] groups, PrintWriter pw) {
114         try (InputStream is =
115                      getClass().getClassLoader().getResourceAsStream("wm_shell_protolog.json")){
116             mViewerConfig.loadViewerConfig(is);
117             return setLogging(true /* setTextLogging */, true, pw, groups);
118         } catch (IOException e) {
119             Log.i(TAG, "Unable to load log definitions: IOException while reading "
120                     + "wm_shell_protolog. " + e);
121         } catch (JSONException e) {
122             Log.i(TAG, "Unable to load log definitions: JSON parsing exception while reading "
123                     + "wm_shell_protolog. " + e);
124         }
125         return -1;
126     }
127 
stopTextLogging(String[] groups, PrintWriter pw)128     public int stopTextLogging(String[] groups, PrintWriter pw) {
129         return setLogging(true /* setTextLogging */, false, pw, groups);
130     }
131 
ShellProtoLogImpl()132     private ShellProtoLogImpl() {
133         super(new File(LOG_FILENAME), null, BUFFER_CAPACITY, new ProtoLogViewerConfigReader());
134     }
135 }
136 
137