1 /* 2 * Copyright (C) 2025 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.adservices.service.profiling; 18 19 import com.android.adservices.service.Flags; 20 import com.android.adservices.service.common.BinderFlagReader; 21 import com.android.adservices.shared.util.Trace; 22 import com.android.internal.annotations.VisibleForTesting; 23 24 import java.util.Set; 25 import java.util.concurrent.atomic.AtomicInteger; 26 27 /** 28 * An abstraction layer used to collect all traces following the same naming convention. 29 * 30 * @hide 31 */ 32 public class RbATraceProvider { 33 private static RbATrace sTrace; 34 private static final Object sLock = new Object(); 35 36 @VisibleForTesting getTrace(Flags flags)37 static RbATrace getTrace(Flags flags) { 38 if (sTrace != null) { 39 return sTrace; 40 } 41 42 synchronized (sLock) { 43 if (sTrace == null) { 44 if (BinderFlagReader.readFlag(flags::getEnableRbAtrace)) { 45 sTrace = new RbATraceImpl(new Trace(), new AtomicInteger()); 46 } else { 47 sTrace = new NoOpRbATrace(); 48 } 49 } 50 51 return sTrace; 52 } 53 } 54 55 /** Should only be used in tests. */ 56 @VisibleForTesting setTrace(RbATrace trace)57 public static void setTrace(RbATrace trace) { 58 sTrace = trace; 59 } 60 61 /** 62 * Writes a trace message for the {@code metricName} to indicate that a given section of code 63 * has begun. The trace name will be concatenated from the {@code featureName} and the {@code 64 * metricName}. 65 * 66 * @param featureName Use the {@code FeatureNames} to specify the feature name. 67 * @param metricName The metric name to appear in the trace. 68 * @param flags for accessing feature flags 69 */ beginSection(String featureName, String metricName, Flags flags)70 public static void beginSection(String featureName, String metricName, Flags flags) { 71 getTrace(flags).beginSection(featureName, metricName); 72 } 73 74 /** 75 * Writes a trace message for the {@code className} {@code methodName} to indicate that a given 76 * section of code has begun. The trace name will be concatenated from the {@code featureName}, 77 * {@code className} and the {@code methodName}. 78 * 79 * @param featureName Use the {@code FeatureNames} to specify the feature name. 80 * @param className The class name to appear in the trace. 81 * @param methodName The method name to appear in the trace. 82 * @param flags for accessing feature flags 83 */ beginSection( String featureName, String className, String methodName, Flags flags)84 public static void beginSection( 85 String featureName, String className, String methodName, Flags flags) { 86 getTrace(flags).beginSection(featureName, className, methodName); 87 } 88 89 /** 90 * Writes a trace message for the {@code metricName} to indicate that a given section of code 91 * has begun. The trace name will be concatenated from the {@code featureName} and the {@code 92 * metricName}. Must be followed by a call to {@code endAsyncSection} with the same {@code 93 * featureName}, {@code metricName} and provided {@code cookie}. Asynchronous events do not need 94 * to be nested. 95 * 96 * @param featureName Use the {@code FeatureNames} to specify the feature name. 97 * @param metricName The metric name to appear in the trace. 98 * @param flags for accessing feature flags 99 * @return unique cookie for identifying trace. 100 */ beginAsyncSection(String featureName, String metricName, Flags flags)101 public static int beginAsyncSection(String featureName, String metricName, Flags flags) { 102 return getTrace(flags).beginAsyncSection(featureName, metricName); 103 } 104 105 /** 106 * Writes a trace message for the {@code className} {@code methodName} to indicate that a given 107 * section of code has begun. The trace name will be concatenated from the {@code featureName}, 108 * {@code className} and {@code methodName}. Must be followed by a call to {@code 109 * endAsyncSection} with the same {@code featureName}, {@code className}, {@code methodName} and 110 * provided {@code cookie}. Asynchronous events do not need to be nested. 111 * 112 * @param className The class name to appear in the trace. 113 * @param methodName The method name to appear in the trace. 114 * @param flags for accessing feature flags 115 * @return unique cookie for identifying trace. 116 */ beginAsyncSection( String featureName, String className, String methodName, Flags flags)117 public static int beginAsyncSection( 118 String featureName, String className, String methodName, Flags flags) { 119 return getTrace(flags).beginAsyncSection(featureName, className, methodName); 120 } 121 122 /** 123 * Writes a trace message to indicate that a given section of code has ended. 124 * 125 * @param flags for accessing feature flags 126 */ endSection(Flags flags)127 public static void endSection(Flags flags) { 128 getTrace(flags).endSection(); 129 } 130 131 /** 132 * Writes a trace message to indicate that a given section of code has ended. Must be called 133 * exactly once for each call to {@code beginAsyncSection(java.lang.String, java.lang.String)} 134 * using the same parameters and provided {@code cookie}. 135 * 136 * @param featureName Use the {@code FeatureNames} to specify the feature name. 137 * @param metricName The metric name to appear in the trace. 138 * @param cookie a unique cookie for identifying trace. 139 * @param flags for accessing feature flags 140 */ endAsyncSection( String featureName, String metricName, int cookie, Flags flags)141 public static void endAsyncSection( 142 String featureName, String metricName, int cookie, Flags flags) { 143 getTrace(flags).endAsyncSection(featureName, metricName, cookie); 144 } 145 146 /** 147 * Writes a trace message to indicate that a given section of code has ended. Must be called 148 * exactly once for each call to {@code beginAsyncSection(java.lang.String, java.lang.String, 149 * java.lang.String)} using the same parameters and provided {@code cookie}. 150 * 151 * @param featureName Use the {@code FeatureNames} to specify the feature name. 152 * @param className The class name to appear in the trace. 153 * @param methodName The method name to appear in the trace. 154 * @param cookie a unique cookie for identifying trace. 155 * @param flags for accessing feature flags 156 */ endAsyncSection( String featureName, String className, String methodName, int cookie, Flags flags)157 public static void endAsyncSection( 158 String featureName, String className, String methodName, int cookie, Flags flags) { 159 getTrace(flags).endAsyncSection(featureName, className, methodName, cookie); 160 } 161 162 /** Feature name to group metrics from the same project together. */ 163 public static final class FeatureNames { 164 public static final String MEASUREMENT_API = "MeasurementApi"; 165 public static final String TOPICS_API = "TopicsApi"; 166 public static final String AD_ID_API = "AdIdApi"; 167 public static final String CONSENT_MANAGER = "ConsentManager"; 168 169 private static final Set<String> VALID_FEATURE_NAMES = 170 Set.of(MEASUREMENT_API, TOPICS_API, AD_ID_API, CONSENT_MANAGER); 171 FeatureNames()172 private FeatureNames() {} 173 isValidFeatureName(String featureName)174 static boolean isValidFeatureName(String featureName) { 175 return VALID_FEATURE_NAMES.contains(featureName); 176 } 177 } 178 } 179