1 /* 2 * Copyright (C) 2023 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.server.credentials.metrics; 18 19 import android.util.Slog; 20 21 import com.android.server.credentials.MetricUtilities; 22 import com.android.server.credentials.metrics.shared.ResponseCollective; 23 24 import java.util.Map; 25 26 /** 27 * The central chosen provider metric object that mimics our defined metric setup. This is used 28 * in the final phase of the flow and emits final status metrics. 29 * Some types are redundant across these metric collectors, but that has debug use-cases as 30 * these data-types are available at different moments of the flow (and typically, one can feed 31 * into the next). 32 */ 33 public class ChosenProviderFinalPhaseMetric { 34 private static final String TAG = "ChosenFinalPhaseMetric"; 35 // The session id associated with this API call, used to unite split emits, for the flow 36 // where we know the calling app 37 private final int mSessionIdCaller; 38 // The session id associated with this API call, used to unite split emits, for the flow 39 // where we know the provider apps 40 private final int mSessionIdProvider; 41 // Reveals if the UI was returned, false by default 42 private boolean mUiReturned = false; 43 private int mChosenUid = -1; 44 45 // Latency figures typically fed in from prior CandidateProviderMetric 46 47 private int mPreQueryPhaseLatencyMicroseconds = -1; 48 private int mQueryPhaseLatencyMicroseconds = -1; 49 50 // Timestamps kept in raw nanoseconds. Expected to be converted to microseconds from using 51 // reference 'mServiceBeganTimeNanoseconds' during metric log point 52 53 // Kept for local reference purposes, the initial timestamp of the service called passed in 54 private long mServiceBeganTimeNanoseconds = -1; 55 // The first query timestamp, which upon emit is normalized to microseconds using the reference 56 // start timestamp 57 private long mQueryStartTimeNanoseconds = -1; 58 // The timestamp at query end, which upon emit will be normalized to microseconds with reference 59 private long mQueryEndTimeNanoseconds = -1; 60 // The UI call timestamp, which upon emit will be normalized to microseconds using reference 61 private long mUiCallStartTimeNanoseconds = -1; 62 // The UI return timestamp, which upon emit will be normalized to microseconds using reference 63 private long mUiCallEndTimeNanoseconds = -1; 64 // The final finish timestamp, which upon emit will be normalized to microseconds with reference 65 private long mFinalFinishTimeNanoseconds = -1; 66 // The status of this provider after selection 67 68 // Other General Information, such as final api status, provider status, entry info, etc... 69 70 private int mChosenProviderStatus = -1; 71 // Indicates if an exception was thrown by this provider, false by default 72 private boolean mHasException = false; 73 // Indicates a framework only exception that occurs in the final phase of the flow 74 private String mFrameworkException = ""; 75 76 // Stores the response credential information, as well as the response entry information which 77 // by default, contains empty info 78 private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of()); 79 // Indicates if this chosen provider was the primary provider, false by default 80 private boolean mIsPrimary = false; 81 82 ChosenProviderFinalPhaseMetric(int sessionIdCaller, int sessionIdProvider)83 public ChosenProviderFinalPhaseMetric(int sessionIdCaller, int sessionIdProvider) { 84 mSessionIdCaller = sessionIdCaller; 85 mSessionIdProvider = sessionIdProvider; 86 } 87 88 /* ------------------- UID ------------------- */ 89 getChosenUid()90 public int getChosenUid() { 91 return mChosenUid; 92 } 93 setChosenUid(int chosenUid)94 public void setChosenUid(int chosenUid) { 95 mChosenUid = chosenUid; 96 } 97 98 /* ---------------- Latencies ------------------ */ 99 100 101 /* ----- Direct Delta Latencies for Local Utility ------- */ 102 103 /** 104 * In order for a chosen provider to be selected, the call must have successfully begun. 105 * Thus, the {@link InitialPhaseMetric} can directly pass this initial latency figure into 106 * this chosen provider metric. 107 * 108 * @param preQueryPhaseLatencyMicroseconds the millisecond latency for the service start, 109 * typically passed in through the 110 * {@link InitialPhaseMetric} 111 */ setPreQueryPhaseLatencyMicroseconds(int preQueryPhaseLatencyMicroseconds)112 public void setPreQueryPhaseLatencyMicroseconds(int preQueryPhaseLatencyMicroseconds) { 113 mPreQueryPhaseLatencyMicroseconds = preQueryPhaseLatencyMicroseconds; 114 } 115 116 /** 117 * In order for a chosen provider to be selected, a candidate provider must exist. The 118 * candidate provider can directly pass the final latency figure into this chosen provider 119 * metric. 120 * 121 * @param queryPhaseLatencyMicroseconds the millisecond latency for the query phase, typically 122 * passed in through the {@link CandidatePhaseMetric} 123 */ setQueryPhaseLatencyMicroseconds(int queryPhaseLatencyMicroseconds)124 public void setQueryPhaseLatencyMicroseconds(int queryPhaseLatencyMicroseconds) { 125 mQueryPhaseLatencyMicroseconds = queryPhaseLatencyMicroseconds; 126 } 127 getPreQueryPhaseLatencyMicroseconds()128 public int getPreQueryPhaseLatencyMicroseconds() { 129 return mPreQueryPhaseLatencyMicroseconds; 130 } 131 getQueryPhaseLatencyMicroseconds()132 public int getQueryPhaseLatencyMicroseconds() { 133 return mQueryPhaseLatencyMicroseconds; 134 } 135 getUiPhaseLatencyMicroseconds()136 public int getUiPhaseLatencyMicroseconds() { 137 return (int) ((mUiCallEndTimeNanoseconds 138 - mUiCallStartTimeNanoseconds) / 1000); 139 } 140 141 /** 142 * Returns the full provider (invocation to response) latency in microseconds. Expects the 143 * start time to be provided, such as from {@link CandidatePhaseMetric}. 144 */ getEntireProviderLatencyMicroseconds()145 public int getEntireProviderLatencyMicroseconds() { 146 return (int) ((mFinalFinishTimeNanoseconds 147 - mQueryStartTimeNanoseconds) / 1000); 148 } 149 150 /** 151 * Returns the full (platform invoked to response) latency in microseconds. Expects the 152 * start time to be provided, such as from {@link InitialPhaseMetric}. 153 */ getEntireLatencyMicroseconds()154 public int getEntireLatencyMicroseconds() { 155 return (int) ((mFinalFinishTimeNanoseconds 156 - mServiceBeganTimeNanoseconds) / 1000); 157 } 158 159 /* ----- Timestamps for Latency ----- */ 160 161 /** 162 * In order for a chosen provider to be selected, the call must have successfully begun. 163 * Thus, the {@link InitialPhaseMetric} can directly pass this initial timestamp into this 164 * chosen provider metric. 165 * 166 * @param serviceBeganTimeNanoseconds the timestamp moment when the platform was called, 167 * typically passed in through the {@link InitialPhaseMetric} 168 */ setServiceBeganTimeNanoseconds(long serviceBeganTimeNanoseconds)169 public void setServiceBeganTimeNanoseconds(long serviceBeganTimeNanoseconds) { 170 mServiceBeganTimeNanoseconds = serviceBeganTimeNanoseconds; 171 } 172 setQueryStartTimeNanoseconds(long queryStartTimeNanoseconds)173 public void setQueryStartTimeNanoseconds(long queryStartTimeNanoseconds) { 174 mQueryStartTimeNanoseconds = queryStartTimeNanoseconds; 175 } 176 setQueryEndTimeNanoseconds(long queryEndTimeNanoseconds)177 public void setQueryEndTimeNanoseconds(long queryEndTimeNanoseconds) { 178 mQueryEndTimeNanoseconds = queryEndTimeNanoseconds; 179 } 180 setUiCallStartTimeNanoseconds(long uiCallStartTimeNanoseconds)181 public void setUiCallStartTimeNanoseconds(long uiCallStartTimeNanoseconds) { 182 mUiCallStartTimeNanoseconds = uiCallStartTimeNanoseconds; 183 } 184 setUiCallEndTimeNanoseconds(long uiCallEndTimeNanoseconds)185 public void setUiCallEndTimeNanoseconds(long uiCallEndTimeNanoseconds) { 186 mUiCallEndTimeNanoseconds = uiCallEndTimeNanoseconds; 187 } 188 setFinalFinishTimeNanoseconds(long finalFinishTimeNanoseconds)189 public void setFinalFinishTimeNanoseconds(long finalFinishTimeNanoseconds) { 190 mFinalFinishTimeNanoseconds = finalFinishTimeNanoseconds; 191 } 192 getServiceBeganTimeNanoseconds()193 public long getServiceBeganTimeNanoseconds() { 194 return mServiceBeganTimeNanoseconds; 195 } 196 getQueryStartTimeNanoseconds()197 public long getQueryStartTimeNanoseconds() { 198 return mQueryStartTimeNanoseconds; 199 } 200 getQueryEndTimeNanoseconds()201 public long getQueryEndTimeNanoseconds() { 202 return mQueryEndTimeNanoseconds; 203 } 204 getUiCallStartTimeNanoseconds()205 public long getUiCallStartTimeNanoseconds() { 206 return mUiCallStartTimeNanoseconds; 207 } 208 getUiCallEndTimeNanoseconds()209 public long getUiCallEndTimeNanoseconds() { 210 return mUiCallEndTimeNanoseconds; 211 } 212 getFinalFinishTimeNanoseconds()213 public long getFinalFinishTimeNanoseconds() { 214 return mFinalFinishTimeNanoseconds; 215 } 216 217 /* --- Time Stamp Conversion to Microseconds from Reference Point --- */ 218 219 /** 220 * We collect raw timestamps in nanoseconds for ease of collection. However, given the scope 221 * of our logging timeframe, and size considerations of the metric, we require these to give us 222 * the microsecond timestamps from the start reference point. 223 * 224 * @param specificTimestamp the timestamp to consider, must be greater than the reference 225 * @return the microsecond integer timestamp from service start to query began 226 */ getTimestampFromReferenceStartMicroseconds(long specificTimestamp)227 public int getTimestampFromReferenceStartMicroseconds(long specificTimestamp) { 228 if (specificTimestamp < mServiceBeganTimeNanoseconds) { 229 Slog.i(TAG, "The timestamp is before service started, falling back to default int"); 230 return MetricUtilities.DEFAULT_INT_32; 231 } 232 return (int) ((specificTimestamp 233 - mServiceBeganTimeNanoseconds) / 1000); 234 } 235 236 /* ----------- Provider Status -------------- */ 237 getChosenProviderStatus()238 public int getChosenProviderStatus() { 239 return mChosenProviderStatus; 240 } 241 setChosenProviderStatus(int chosenProviderStatus)242 public void setChosenProviderStatus(int chosenProviderStatus) { 243 mChosenProviderStatus = chosenProviderStatus; 244 } 245 246 /* ----------- Session ID -------------- */ 247 getSessionIdProvider()248 public int getSessionIdProvider() { 249 return mSessionIdProvider; 250 } 251 252 /* ----------- UI Returned Successfully -------------- */ 253 setUiReturned(boolean uiReturned)254 public void setUiReturned(boolean uiReturned) { 255 mUiReturned = uiReturned; 256 } 257 isUiReturned()258 public boolean isUiReturned() { 259 return mUiReturned; 260 } 261 262 /* -------------- Has Exception ---------------- */ 263 setHasException(boolean hasException)264 public void setHasException(boolean hasException) { 265 mHasException = hasException; 266 } 267 isHasException()268 public boolean isHasException() { 269 return mHasException; 270 } 271 272 /* -------------- The Entries and Responses Gathered ---------------- */ 273 setResponseCollective(ResponseCollective responseCollective)274 public void setResponseCollective(ResponseCollective responseCollective) { 275 mResponseCollective = responseCollective; 276 } 277 getResponseCollective()278 public ResponseCollective getResponseCollective() { 279 return mResponseCollective; 280 } 281 282 /* -------------- Framework Exception ---------------- */ 283 setFrameworkException(String frameworkException)284 public void setFrameworkException(String frameworkException) { 285 mFrameworkException = frameworkException; 286 } 287 getFrameworkException()288 public String getFrameworkException() { 289 return mFrameworkException; 290 } 291 292 /* -------------- Session ID for Track One (Known Calling App) ---------------- */ 293 getSessionIdCaller()294 public int getSessionIdCaller() { 295 return mSessionIdCaller; 296 } 297 setPrimary(boolean primary)298 public void setPrimary(boolean primary) { 299 mIsPrimary = primary; 300 } 301 isPrimary()302 public boolean isPrimary() { 303 return mIsPrimary; 304 } 305 } 306