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 public class MetricsLogger { 38 // define metric categories in frameworks/base/proto/src/metrics_constants.proto. 39 // mirror changes in native version at system/core/libmetricslogger/metrics_logger.cpp 40 41 private static MetricsLogger sMetricsLogger; 42 43 @UnsupportedAppUsage MetricsLogger()44 public MetricsLogger() { 45 } 46 getLogger()47 private static MetricsLogger getLogger() { 48 if (sMetricsLogger == null) { 49 sMetricsLogger = new MetricsLogger(); 50 } 51 return sMetricsLogger; 52 } 53 saveLog(LogMaker log)54 protected void saveLog(LogMaker log) { 55 EventLogTags.writeSysuiMultiAction(log.serialize()); 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(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 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