1 /* 2 * Copyright (C) 2015 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 package com.android.internal.logging; 17 18 import android.annotation.UnsupportedAppUsage; 19 import android.content.Context; 20 import android.metrics.LogMaker; 21 import android.os.Build; 22 import android.util.StatsLog; 23 import android.view.View; 24 25 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 26 27 /** 28 * Writes sysui_multi_event records to the system event log. 29 * 30 * Prefer the methods write(LogMaker), or count() or histogram(). Replace legacy methods with 31 * their current equivalents when the opportunity arises. 32 * 33 * This class is a lightweight dependency barrier - it is cheap and easy to construct. 34 * Logging is also cheap, so it is not normally necessary to move logging off of the UI thread. 35 * 36 * @hide 37 */ 38 public class MetricsLogger { 39 // define metric categories in frameworks/base/proto/src/metrics_constants.proto. 40 // mirror changes in native version at system/core/libmetricslogger/metrics_logger.cpp 41 42 private static MetricsLogger sMetricsLogger; 43 getLogger()44 private static MetricsLogger getLogger() { 45 if (sMetricsLogger == null) { 46 sMetricsLogger = new MetricsLogger(); 47 } 48 return sMetricsLogger; 49 } 50 saveLog(LogMaker log)51 protected void saveLog(LogMaker log) { 52 // TODO(b/116684537): Flag guard logging to event log and statsd socket. 53 EventLogTags.writeSysuiMultiAction(log.serialize()); 54 StatsLog.write(StatsLog.KEY_VALUE_PAIRS_ATOM, /* UID is retrieved from statsd side */ 0, 55 log.getEntries()); 56 } 57 58 public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN; 59 public static final int LOGTAG = EventLogTags.SYSUI_MULTI_ACTION; 60 61 /** Write an event log record, consisting of content.serialize(). */ 62 @UnsupportedAppUsage write(LogMaker content)63 public void write(LogMaker content) { 64 if (content.getType() == MetricsEvent.TYPE_UNKNOWN) { 65 content.setType(MetricsEvent.TYPE_ACTION); 66 } 67 saveLog(content); 68 } 69 70 /** Add an integer value to the monotonically increasing counter with the given name. */ count(String name, int value)71 public void count(String name, int value) { 72 saveLog(new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER) 73 .setCounterName(name) 74 .setCounterValue(value)); 75 } 76 77 /** Increment the bucket with the integer label on the histogram with the given name. */ histogram(String name, int bucket)78 public void histogram(String name, int bucket) { 79 // see LogHistogram in system/core/libmetricslogger/metrics_logger.cpp 80 saveLog(new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM) 81 .setCounterName(name) 82 .setCounterBucket(bucket) 83 .setCounterValue(1)); 84 } 85 86 /* Legacy logging methods follow. These are all simple shorthands and can be replaced 87 * with an equivalent write(). */ 88 89 /** Logs an OPEN event on the category. 90 * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_OPEN)) */ visible(int category)91 public void visible(int category) throws IllegalArgumentException { 92 if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { 93 throw new IllegalArgumentException("Must define metric category"); 94 } 95 saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_OPEN)); 96 } 97 98 /** Logs a CLOSE event on the category. 99 * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_CLOSE)) */ hidden(int category)100 public void hidden(int category) throws IllegalArgumentException { 101 if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { 102 throw new IllegalArgumentException("Must define metric category"); 103 } 104 saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_CLOSE)); 105 } 106 107 /** Logs an OPEN or CLOSE event on the category, depending on visible. 108 * Equivalent to write(new LogMaker(category) 109 * .setType(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)) */ visibility(int category, boolean visible)110 public void visibility(int category, boolean visible) 111 throws IllegalArgumentException { 112 if (visible) { 113 visible(category); 114 } else { 115 hidden(category); 116 } 117 } 118 119 /** Logs an OPEN or CLOSE event on the category, depending on vis. 120 * Equivalent to write(new LogMaker(category) 121 .setType(vis == View.VISIBLE ? 122 MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)) */ visibility(int category, int vis)123 public void visibility(int category, int vis) 124 throws IllegalArgumentException { 125 visibility(category, vis == View.VISIBLE); 126 } 127 128 /** Logs an ACTION event on the category. 129 * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION)) */ action(int category)130 public void action(int category) { 131 saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION)); 132 } 133 134 /** Logs an ACTION event on the category. 135 * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION) 136 .setSubtype(value) */ action(int category, int value)137 public void action(int category, int value) { 138 saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION).setSubtype(value)); 139 } 140 141 /** Logs an ACTION event on the category. 142 * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION) 143 .setSubtype(value ? 1 : 0) */ action(int category, boolean value)144 public void action(int category, boolean value) { 145 saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION).setSubtype(value ? 1 : 0)); 146 } 147 148 /** Logs an ACTION event on the category. 149 * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION) 150 .setPackageName(value ? 1 : 0) */ action(int category, String pkg)151 public void action(int category, String pkg) { 152 if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { 153 throw new IllegalArgumentException("Must define metric category"); 154 } 155 saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION).setPackageName(pkg)); 156 } 157 158 /** @deprecated because untestable; use {@link #visible(int)} */ 159 @Deprecated visible(Context context, int category)160 public static void visible(Context context, int category) throws IllegalArgumentException { 161 getLogger().visible(category); 162 } 163 164 /** @deprecated because untestable; use {@link #hidden(int)} */ 165 @Deprecated hidden(Context context, int category)166 public static void hidden(Context context, int category) throws IllegalArgumentException { 167 getLogger().hidden(category); 168 } 169 170 /** @deprecated because untestable; use {@link #visibility(int, boolean)} */ 171 @Deprecated visibility(Context context, int category, boolean visibile)172 public static void visibility(Context context, int category, boolean visibile) 173 throws IllegalArgumentException { 174 getLogger().visibility(category, visibile); 175 } 176 177 /** @deprecated because untestable; use {@link #visibility(int, int)} */ 178 @Deprecated visibility(Context context, int category, int vis)179 public static void visibility(Context context, int category, int vis) 180 throws IllegalArgumentException { 181 visibility(context, category, vis == View.VISIBLE); 182 } 183 184 /** @deprecated because untestable; use {@link #action(int)} */ 185 @Deprecated action(Context context, int category)186 public static void action(Context context, int category) { 187 getLogger().action(category); 188 } 189 190 /** @deprecated because untestable; use {@link #action(int, int)} */ 191 @Deprecated action(Context context, int category, int value)192 public static void action(Context context, int category, int value) { 193 getLogger().action(category, value); 194 } 195 196 /** @deprecated because untestable; use {@link #action(int, boolean)} */ 197 @Deprecated action(Context context, int category, boolean value)198 public static void action(Context context, int category, boolean value) { 199 getLogger().action(category, value); 200 } 201 202 /** @deprecated because untestable; use {@link #write(LogMaker)} */ 203 @Deprecated action(LogMaker content)204 public static void action(LogMaker content) { 205 getLogger().write(content); 206 } 207 208 /** @deprecated because untestable; use {@link #action(int, String)} */ 209 @Deprecated action(Context context, int category, String pkg)210 public static void action(Context context, int category, String pkg) { 211 getLogger().action(category, pkg); 212 } 213 214 /** 215 * Add an integer value to the monotonically increasing counter with the given name. 216 * @deprecated because untestable; use {@link #count(String, int)} 217 */ 218 @Deprecated count(Context context, String name, int value)219 public static void count(Context context, String name, int value) { 220 getLogger().count(name, value); 221 } 222 223 /** 224 * Increment the bucket with the integer label on the histogram with the given name. 225 * @deprecated use {@link #histogram(String, int)} 226 */ 227 @Deprecated histogram(Context context, String name, int bucket)228 public static void histogram(Context context, String name, int bucket) { 229 getLogger().histogram(name, bucket); 230 } 231 } 232