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