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