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