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 mOemUiUid = -1; 71 private int mFallbackUiUid = -1; 72 private OemUiUsageStatus mOemUiUsageStatus = OemUiUsageStatus.UNKNOWN; 73 74 private int mChosenProviderStatus = -1; 75 // Indicates if an exception was thrown by this provider, false by default 76 private boolean mHasException = false; 77 // Indicates a framework only exception that occurs in the final phase of the flow 78 private String mFrameworkException = ""; 79 80 // Stores the response credential information, as well as the response entry information which 81 // by default, contains empty info 82 private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of()); 83 // Indicates if this chosen provider was the primary provider, false by default 84 private boolean mIsPrimary = false; 85 86 private String mChosenClassType = ""; 87 88 ChosenProviderFinalPhaseMetric(int sessionIdCaller, int sessionIdProvider)89 public ChosenProviderFinalPhaseMetric(int sessionIdCaller, int sessionIdProvider) { 90 mSessionIdCaller = sessionIdCaller; 91 mSessionIdProvider = sessionIdProvider; 92 } 93 94 /* ------------------- Chosen Credential ------------------- */ 95 setChosenClassType(String clickedClassType)96 public void setChosenClassType(String clickedClassType) { 97 mChosenClassType = clickedClassType; 98 } 99 getChosenClassType()100 public String getChosenClassType() { 101 return mChosenClassType; 102 } 103 104 /* ------------------- UID ------------------- */ 105 getChosenUid()106 public int getChosenUid() { 107 return mChosenUid; 108 } 109 setChosenUid(int chosenUid)110 public void setChosenUid(int chosenUid) { 111 mChosenUid = chosenUid; 112 } 113 114 /* ---------------- Latencies ------------------ */ 115 116 117 /* ----- Direct Delta Latencies for Local Utility ------- */ 118 119 /** 120 * In order for a chosen provider to be selected, the call must have successfully begun. 121 * Thus, the {@link InitialPhaseMetric} can directly pass this initial latency figure into 122 * this chosen provider metric. 123 * 124 * @param preQueryPhaseLatencyMicroseconds the millisecond latency for the service start, 125 * typically passed in through the 126 * {@link InitialPhaseMetric} 127 */ setPreQueryPhaseLatencyMicroseconds(int preQueryPhaseLatencyMicroseconds)128 public void setPreQueryPhaseLatencyMicroseconds(int preQueryPhaseLatencyMicroseconds) { 129 mPreQueryPhaseLatencyMicroseconds = preQueryPhaseLatencyMicroseconds; 130 } 131 132 /** 133 * In order for a chosen provider to be selected, a candidate provider must exist. The 134 * candidate provider can directly pass the final latency figure into this chosen provider 135 * metric. 136 * 137 * @param queryPhaseLatencyMicroseconds the millisecond latency for the query phase, typically 138 * passed in through the {@link CandidatePhaseMetric} 139 */ setQueryPhaseLatencyMicroseconds(int queryPhaseLatencyMicroseconds)140 public void setQueryPhaseLatencyMicroseconds(int queryPhaseLatencyMicroseconds) { 141 mQueryPhaseLatencyMicroseconds = queryPhaseLatencyMicroseconds; 142 } 143 getPreQueryPhaseLatencyMicroseconds()144 public int getPreQueryPhaseLatencyMicroseconds() { 145 return mPreQueryPhaseLatencyMicroseconds; 146 } 147 getQueryPhaseLatencyMicroseconds()148 public int getQueryPhaseLatencyMicroseconds() { 149 return mQueryPhaseLatencyMicroseconds; 150 } 151 getUiPhaseLatencyMicroseconds()152 public int getUiPhaseLatencyMicroseconds() { 153 return (int) ((mUiCallEndTimeNanoseconds 154 - mUiCallStartTimeNanoseconds) / 1000); 155 } 156 157 /** 158 * Returns the full provider (invocation to response) latency in microseconds. Expects the 159 * start time to be provided, such as from {@link CandidatePhaseMetric}. 160 */ getEntireProviderLatencyMicroseconds()161 public int getEntireProviderLatencyMicroseconds() { 162 return (int) ((mFinalFinishTimeNanoseconds 163 - mQueryStartTimeNanoseconds) / 1000); 164 } 165 166 /** 167 * Returns the full (platform invoked to response) latency in microseconds. Expects the 168 * start time to be provided, such as from {@link InitialPhaseMetric}. 169 */ getEntireLatencyMicroseconds()170 public int getEntireLatencyMicroseconds() { 171 return (int) ((mFinalFinishTimeNanoseconds 172 - mServiceBeganTimeNanoseconds) / 1000); 173 } 174 175 /* ----- Timestamps for Latency ----- */ 176 177 /** 178 * In order for a chosen provider to be selected, the call must have successfully begun. 179 * Thus, the {@link InitialPhaseMetric} can directly pass this initial timestamp into this 180 * chosen provider metric. 181 * 182 * @param serviceBeganTimeNanoseconds the timestamp moment when the platform was called, 183 * typically passed in through the {@link InitialPhaseMetric} 184 */ setServiceBeganTimeNanoseconds(long serviceBeganTimeNanoseconds)185 public void setServiceBeganTimeNanoseconds(long serviceBeganTimeNanoseconds) { 186 mServiceBeganTimeNanoseconds = serviceBeganTimeNanoseconds; 187 } 188 setQueryStartTimeNanoseconds(long queryStartTimeNanoseconds)189 public void setQueryStartTimeNanoseconds(long queryStartTimeNanoseconds) { 190 mQueryStartTimeNanoseconds = queryStartTimeNanoseconds; 191 } 192 setQueryEndTimeNanoseconds(long queryEndTimeNanoseconds)193 public void setQueryEndTimeNanoseconds(long queryEndTimeNanoseconds) { 194 mQueryEndTimeNanoseconds = queryEndTimeNanoseconds; 195 } 196 setUiCallStartTimeNanoseconds(long uiCallStartTimeNanoseconds)197 public void setUiCallStartTimeNanoseconds(long uiCallStartTimeNanoseconds) { 198 mUiCallStartTimeNanoseconds = uiCallStartTimeNanoseconds; 199 } 200 setUiCallEndTimeNanoseconds(long uiCallEndTimeNanoseconds)201 public void setUiCallEndTimeNanoseconds(long uiCallEndTimeNanoseconds) { 202 mUiCallEndTimeNanoseconds = uiCallEndTimeNanoseconds; 203 } 204 setFinalFinishTimeNanoseconds(long finalFinishTimeNanoseconds)205 public void setFinalFinishTimeNanoseconds(long finalFinishTimeNanoseconds) { 206 mFinalFinishTimeNanoseconds = finalFinishTimeNanoseconds; 207 } 208 getServiceBeganTimeNanoseconds()209 public long getServiceBeganTimeNanoseconds() { 210 return mServiceBeganTimeNanoseconds; 211 } 212 getQueryStartTimeNanoseconds()213 public long getQueryStartTimeNanoseconds() { 214 return mQueryStartTimeNanoseconds; 215 } 216 getQueryEndTimeNanoseconds()217 public long getQueryEndTimeNanoseconds() { 218 return mQueryEndTimeNanoseconds; 219 } 220 getUiCallStartTimeNanoseconds()221 public long getUiCallStartTimeNanoseconds() { 222 return mUiCallStartTimeNanoseconds; 223 } 224 getUiCallEndTimeNanoseconds()225 public long getUiCallEndTimeNanoseconds() { 226 return mUiCallEndTimeNanoseconds; 227 } 228 getFinalFinishTimeNanoseconds()229 public long getFinalFinishTimeNanoseconds() { 230 return mFinalFinishTimeNanoseconds; 231 } 232 233 /* --- Time Stamp Conversion to Microseconds from Reference Point --- */ 234 235 /** 236 * We collect raw timestamps in nanoseconds for ease of collection. However, given the scope 237 * of our logging timeframe, and size considerations of the metric, we require these to give us 238 * the microsecond timestamps from the start reference point. 239 * 240 * @param specificTimestamp the timestamp to consider, must be greater than the reference 241 * @return the microsecond integer timestamp from service start to query began 242 */ getTimestampFromReferenceStartMicroseconds(long specificTimestamp)243 public int getTimestampFromReferenceStartMicroseconds(long specificTimestamp) { 244 if (specificTimestamp < mServiceBeganTimeNanoseconds) { 245 Slog.i(TAG, "The timestamp is before service started, falling back to default int"); 246 return MetricUtilities.DEFAULT_INT_32; 247 } 248 return (int) ((specificTimestamp 249 - mServiceBeganTimeNanoseconds) / 1000); 250 } 251 252 /* ----------- Provider Status -------------- */ 253 getChosenProviderStatus()254 public int getChosenProviderStatus() { 255 return mChosenProviderStatus; 256 } 257 setChosenProviderStatus(int chosenProviderStatus)258 public void setChosenProviderStatus(int chosenProviderStatus) { 259 mChosenProviderStatus = chosenProviderStatus; 260 } 261 262 /* ----------- Session ID -------------- */ 263 getSessionIdProvider()264 public int getSessionIdProvider() { 265 return mSessionIdProvider; 266 } 267 268 /* ----------- UI Returned Successfully -------------- */ 269 setUiReturned(boolean uiReturned)270 public void setUiReturned(boolean uiReturned) { 271 mUiReturned = uiReturned; 272 } 273 isUiReturned()274 public boolean isUiReturned() { 275 return mUiReturned; 276 } 277 278 /* -------------- Has Exception ---------------- */ 279 setHasException(boolean hasException)280 public void setHasException(boolean hasException) { 281 mHasException = hasException; 282 } 283 isHasException()284 public boolean isHasException() { 285 return mHasException; 286 } 287 288 /* -------------- The Entries and Responses Gathered ---------------- */ 289 setResponseCollective(ResponseCollective responseCollective)290 public void setResponseCollective(ResponseCollective responseCollective) { 291 mResponseCollective = responseCollective; 292 } 293 getResponseCollective()294 public ResponseCollective getResponseCollective() { 295 return mResponseCollective; 296 } 297 298 /* -------------- Framework Exception ---------------- */ 299 setFrameworkException(String frameworkException)300 public void setFrameworkException(String frameworkException) { 301 mFrameworkException = frameworkException; 302 } 303 getFrameworkException()304 public String getFrameworkException() { 305 return mFrameworkException; 306 } 307 308 /* -------------- Session ID for Track One (Known Calling App) ---------------- */ 309 getSessionIdCaller()310 public int getSessionIdCaller() { 311 return mSessionIdCaller; 312 } 313 setPrimary(boolean primary)314 public void setPrimary(boolean primary) { 315 mIsPrimary = primary; 316 } 317 isPrimary()318 public boolean isPrimary() { 319 return mIsPrimary; 320 } 321 setOemUiUid(int oemUiUid)322 public void setOemUiUid(int oemUiUid) { 323 mOemUiUid = oemUiUid; 324 } 325 getOemUiUid()326 public int getOemUiUid() { 327 return mOemUiUid; 328 } 329 setFallbackUiUid(int fallbackUiUid)330 public void setFallbackUiUid(int fallbackUiUid) { 331 mFallbackUiUid = fallbackUiUid; 332 } 333 getFallbackUiUid()334 public int getFallbackUiUid() { 335 return mFallbackUiUid; 336 } 337 setOemUiUsageStatus(OemUiUsageStatus oemUiUsageStatus)338 public void setOemUiUsageStatus(OemUiUsageStatus oemUiUsageStatus) { 339 mOemUiUsageStatus = oemUiUsageStatus; 340 } 341 getOemUiUsageStatus()342 public int getOemUiUsageStatus() { 343 return mOemUiUsageStatus.getLoggingInt(); 344 } 345 } 346