Merge "Candidate Metric Utilized in Framework" into udc-dev

This commit is contained in:
Arpan Kaphle
2023-03-15 17:03:14 +00:00
committed by Android (Google) Code Review
9 changed files with 231 additions and 90 deletions

View File

@@ -168,7 +168,7 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
Log.i(TAG, "respondToClientWithErrorAndFinish");
// TODO add exception bit
if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
Log.i(TAG, "Request has already been completed. This is strange.");
return;

View File

@@ -592,9 +592,13 @@ public final class CredentialManagerService
}
private void finalizeAndEmitInitialPhaseMetric(RequestSession session) {
var initMetric = session.mInitialPhaseMetric;
initMetric.setCredentialServiceBeginQueryTimeNanoseconds(System.nanoTime());
MetricUtilities.logApiCalled(initMetric);
try {
var initMetric = session.mInitialPhaseMetric;
initMetric.setCredentialServiceBeginQueryTimeNanoseconds(System.nanoTime());
MetricUtilities.logApiCalled(initMetric);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@Override

View File

@@ -80,6 +80,34 @@ public class MetricUtilities {
return (int) ((t2 - t1) / 1000);
}
/**
* A logging utility used primarily for the candidate phase of the current metric setup.
*
* @param providers a map with known providers
* @param emitSequenceId an emitted sequence id for the current session
*/
protected static void logApiCalled(Map<String, ProviderSession> providers,
int emitSequenceId) {
try {
var providerSessions = providers.values();
int providerSize = providerSessions.size();
int[] candidateUidList = new int[providerSize];
int[] candidateQueryRoundTripTimeList = new int[providerSize];
int[] candidateStatusList = new int[providerSize];
int index = 0;
for (var session : providerSessions) {
CandidatePhaseMetric metric = session.mCandidatePhasePerProviderMetric;
candidateUidList[index] = metric.getCandidateUid();
candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMicroseconds();
candidateStatusList[index] = metric.getProviderQueryStatus();
index++;
}
// TODO Handle the emit here
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
/**
* The most common logging helper, handles the overall status of the API request with the
* provider status and latencies. Other versions of this method may be more useful depending
@@ -90,6 +118,7 @@ public class MetricUtilities {
* @param providers a map with known providers
* @param callingUid the calling UID of the client app
* @param chosenProviderFinalPhaseMetric the metric data type of the final chosen provider
* TODO remove soon
*/
protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
Map<String, ProviderSession> providers, int callingUid,
@@ -133,6 +162,7 @@ public class MetricUtilities {
* contain default values for all other optional parameters.
*
* TODO(b/271135048) - given space requirements, this may be a good candidate for another atom
* TODO immediately remove and carry over TODO to new log for this setup
*
* @param apiName the api name to log
* @param apiStatus the status to log

View File

@@ -33,7 +33,7 @@ import android.util.Slog;
*
* @hide
*/
public final class ProviderClearSession extends ProviderSession<ClearCredentialStateRequest,
public final class ProviderClearSession extends ProviderSession<ClearCredentialStateRequest,
Void>
implements
RemoteCredentialService.ProviderCallbacks<Void> {
@@ -42,7 +42,8 @@ public final class ProviderClearSession extends ProviderSession<ClearCredential
private ClearCredentialStateException mProviderException;
/** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderClearSession createNewSession(
@Nullable
public static ProviderClearSession createNewSession(
Context context,
@UserIdInt int userId,
CredentialProviderInfo providerInfo,
@@ -53,7 +54,7 @@ public final class ProviderClearSession extends ProviderSession<ClearCredential
clearRequestSession.mClientRequest,
clearRequestSession.mClientAppInfo);
return new ProviderClearSession(context, providerInfo, clearRequestSession, userId,
remoteCredentialService, providerRequest);
remoteCredentialService, providerRequest);
}
@Nullable
@@ -90,6 +91,7 @@ public final class ProviderClearSession extends ProviderSession<ClearCredential
if (exception instanceof ClearCredentialStateException) {
mProviderException = (ClearCredentialStateException) exception;
}
captureCandidateFailure();
updateStatusAndInvokeCallback(toStatus(errorCode));
}
@@ -120,14 +122,7 @@ public final class ProviderClearSession extends ProviderSession<ClearCredential
@Override
protected void invokeSession() {
if (mRemoteCredentialService != null) {
/*
InitialPhaseMetric initMetric = ((RequestSession)mCallbacks).initMetric;
TODO immediately once the other change patched through
mCandidateProviderMetric.setSessionId(initMetric
.mInitialPhaseMetric.getSessionId());
mCandidateProviderMetric.setStartTime(initMetric.getStartTime())
*/
mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
startCandidateMetrics();
mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
}
}

View File

@@ -40,6 +40,8 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import com.android.server.credentials.metrics.EntryEnum;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -65,7 +67,8 @@ public final class ProviderCreateSession extends ProviderSession<
private final ProviderResponseDataHandler mProviderResponseDataHandler;
/** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderCreateSession createNewSession(
@Nullable
public static ProviderCreateSession createNewSession(
Context context,
@UserIdInt int userId,
CredentialProviderInfo providerInfo,
@@ -155,6 +158,7 @@ public final class ProviderCreateSession extends ProviderSession<
// Store query phase exception for aggregation with final response
mProviderException = (CreateCredentialException) exception;
}
captureCandidateFailure();
updateStatusAndInvokeCallback(toStatus(errorCode));
}
@@ -175,14 +179,32 @@ public final class ProviderCreateSession extends ProviderSession<
mProviderResponseDataHandler.addResponseContent(response.getCreateEntries(),
response.getRemoteCreateEntry());
if (mProviderResponseDataHandler.isEmptyResponse(response)) {
gatheCandidateEntryMetrics(response);
updateStatusAndInvokeCallback(Status.EMPTY_RESPONSE);
} else {
gatheCandidateEntryMetrics(response);
updateStatusAndInvokeCallback(Status.SAVE_ENTRIES_RECEIVED);
}
}
private void gatheCandidateEntryMetrics(BeginCreateCredentialResponse response) {
try {
var createEntries = response.getCreateEntries();
int numCreateEntries = createEntries == null ? 0 : createEntries.size();
// TODO confirm how to get types from slice
if (numCreateEntries > 0) {
createEntries.forEach(c ->
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.CREDENTIAL_ENTRY));
}
mCandidatePhasePerProviderMetric.setNumEntriesTotal(numCreateEntries);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@Override
@Nullable protected CreateCredentialProviderData prepareUiData()
@Nullable
protected CreateCredentialProviderData prepareUiData()
throws IllegalArgumentException {
Log.i(TAG, "In prepareUiData");
if (!ProviderSession.isUiInvokingStatus(getStatus())) {
@@ -226,14 +248,7 @@ public final class ProviderCreateSession extends ProviderSession<
@Override
protected void invokeSession() {
if (mRemoteCredentialService != null) {
/*
InitialPhaseMetric initMetric = ((RequestSession)mCallbacks).initMetric;
TODO immediately once the other change patched through
mCandidateProviderMetric.setSessionId(initMetric
.mInitialPhaseMetric.getSessionId());
mCandidateProviderMetric.setStartTime(initMetric.getStartTime())
*/
mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
startCandidateMetrics();
mRemoteCredentialService.onCreateCredential(mProviderRequest, this);
}
}
@@ -305,12 +320,14 @@ public final class ProviderCreateSession extends ProviderSession<
}
private class ProviderResponseDataHandler {
@Nullable private final ComponentName mExpectedRemoteEntryProviderService;
@Nullable
private final ComponentName mExpectedRemoteEntryProviderService;
@NonNull
private final Map<String, Pair<CreateEntry, Entry>> mUiCreateEntries = new HashMap<>();
@Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
@Nullable
private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(@Nullable ComponentName expectedRemoteEntryProviderService) {
mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
@@ -323,6 +340,7 @@ public final class ProviderCreateSession extends ProviderSession<
setRemoteEntry(remoteEntry);
}
}
public void addCreateEntry(CreateEntry createEntry) {
String id = generateUniqueId();
Entry entry = new Entry(SAVE_ENTRY_KEY,
@@ -373,6 +391,7 @@ public final class ProviderCreateSession extends ProviderSession<
private boolean isEmptyResponse() {
return mUiCreateEntries.isEmpty() && mUiRemoteEntry == null;
}
@Nullable
public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry == null || mUiRemoteEntry

View File

@@ -43,6 +43,8 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import com.android.server.credentials.metrics.EntryEnum;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -82,7 +84,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private final ProviderResponseDataHandler mProviderResponseDataHandler;
/** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderGetSession createNewSession(
@Nullable
public static ProviderGetSession createNewSession(
Context context,
@UserIdInt int userId,
CredentialProviderInfo providerInfo,
@@ -113,6 +116,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
Log.i(TAG, "Unable to create provider session");
return null;
}
private static BeginGetCredentialRequest constructQueryPhaseRequest(
android.credentials.GetCredentialRequest filteredRequest,
CallingAppInfo callingAppInfo,
@@ -169,7 +173,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
CallingAppInfo callingAppInfo,
Map<String, CredentialOption> beginGetOptionToCredentialOptionMap,
String hybridService) {
super(context, beginGetRequest, callbacks, info.getComponentName() ,
super(context, beginGetRequest, callbacks, info.getComponentName(),
userId, remoteCredentialService);
mCompleteRequest = completeGetRequest;
mCallingAppInfo = callingAppInfo;
@@ -191,6 +195,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
if (exception instanceof GetCredentialException) {
mProviderException = (GetCredentialException) exception;
}
captureCandidateFailure();
updateStatusAndInvokeCallback(toStatus(errorCode));
}
@@ -269,20 +274,14 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
@Override
protected void invokeSession() {
if (mRemoteCredentialService != null) {
/*
InitialPhaseMetric initMetric = ((RequestSession)mCallbacks).initMetric;
TODO immediately once the other change patched through
mCandidateProviderMetric.setSessionId(initMetric
.mInitialPhaseMetric.getSessionId());
mCandidateProviderMetric.setStartTime(initMetric.getStartTime())
*/
mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
startCandidateMetrics();
mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
}
}
@Override // Call from request session to data to be shown on the UI
@Nullable protected GetCredentialProviderData prepareUiData() throws IllegalArgumentException {
@Nullable
protected GetCredentialProviderData prepareUiData() throws IllegalArgumentException {
Log.i(TAG, "In prepareUiData");
if (!ProviderSession.isUiInvokingStatus(getStatus())) {
Log.i(TAG, "In prepareUiData - provider does not want to show UI: "
@@ -389,6 +388,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
GetCredentialException exception = maybeGetPendingIntentException(
providerPendingIntentResponse);
if (exception != null) {
// TODO (b/271135048), for AuthenticationEntry callback selection, set error
invokeCallbackWithError(exception.getType(),
exception.getMessage());
// Additional content received is in the form of an exception which ends the flow.
@@ -439,11 +439,34 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
updateStatusAndInvokeCallback(Status.EMPTY_RESPONSE);
return;
}
// TODO immediately, add to Candidate Phase counts, repeat across all sessions
// Use sets to dedup type counts
gatherCandidateEntryMetrics(response);
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
}
private void gatherCandidateEntryMetrics(BeginGetCredentialResponse response) {
try {
int numCredEntries = response.getCredentialEntries().size();
int numActionEntries = response.getActions().size();
int numAuthEntries = response.getAuthenticationActions().size();
// TODO immediately add remote entries
// TODO immediately confirm how to get types from slice to get unique type count via
// dedupe
response.getCredentialEntries().forEach(c ->
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.CREDENTIAL_ENTRY));
response.getActions().forEach(c ->
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.ACTION_ENTRY));
response.getAuthenticationActions().forEach(c ->
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.AUTHENTICATION_ENTRY));
mCandidatePhasePerProviderMetric.setNumEntriesTotal(numCredEntries + numAuthEntries
+ numActionEntries);
mCandidatePhasePerProviderMetric.setCredentialEntryCount(numCredEntries);
mCandidatePhasePerProviderMetric.setActionEntryCount(numActionEntries);
mCandidatePhasePerProviderMetric.setAuthenticationEntryCount(numAuthEntries);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
/**
* When an invalid state occurs, e.g. entry mismatch or no response from provider,
* we send back a TYPE_NO_CREDENTIAL error as to the developer.
@@ -471,11 +494,12 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
|| e.second.getStatus()
== AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT
);
);
}
private class ProviderResponseDataHandler {
@Nullable private final ComponentName mExpectedRemoteEntryProviderService;
@Nullable
private final ComponentName mExpectedRemoteEntryProviderService;
@NonNull
private final Map<String, Pair<CredentialEntry, Entry>> mUiCredentialEntries =
new HashMap<>();
@@ -485,7 +509,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private final Map<String, Pair<Action, AuthenticationEntry>> mUiAuthenticationEntries =
new HashMap<>();
@Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
@Nullable
private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(@Nullable ComponentName expectedRemoteEntryProviderService) {
mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
@@ -509,6 +534,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
setRemoteEntry(remoteEntry);
}
}
public void addCredentialEntry(CredentialEntry credentialEntry) {
String id = generateUniqueId();
Entry entry = new Entry(CREDENTIAL_ENTRY_KEY,
@@ -559,7 +585,6 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
public GetCredentialProviderData toGetCredentialProviderData() {
return new GetCredentialProviderData.Builder(
mComponentName.flattenToString()).setActionChips(prepareActionEntries())

View File

@@ -32,6 +32,7 @@ import android.os.RemoteException;
import android.util.Log;
import com.android.server.credentials.metrics.CandidatePhaseMetric;
import com.android.server.credentials.metrics.InitialPhaseMetric;
import com.android.server.credentials.metrics.ProviderStatusForMetrics;
import java.util.UUID;
@@ -72,8 +73,9 @@ public abstract class ProviderSession<T, R>
@NonNull
protected Boolean mProviderResponseSet = false;
// Specific candidate provider metric for the provider this session handles
@Nullable
protected CandidatePhaseMetric mCandidatePhasePerProviderMetric;
@NonNull
protected final CandidatePhaseMetric mCandidatePhasePerProviderMetric =
new CandidatePhaseMetric();
@NonNull
private int mProviderSessionUid;
@@ -143,7 +145,6 @@ public abstract class ProviderSession<T, R>
mUserId = userId;
mComponentName = componentName;
mRemoteCredentialService = remoteCredentialService;
mCandidatePhasePerProviderMetric = new CandidatePhaseMetric();
mProviderSessionUid = MetricUtilities.getPackageUid(mContext, mComponentName);
}
@@ -208,6 +209,12 @@ public abstract class ProviderSession<T, R>
return mRemoteCredentialService;
}
protected void captureCandidateFailure() {
mCandidatePhasePerProviderMetric.setHasException(true);
// TODO(b/271135048) - this is a true exception, but what about the empty case?
// Add more nuance in next iteration.
}
/** Updates the status . */
protected void updateStatusAndInvokeCallback(@NonNull Status status) {
setStatus(status);
@@ -216,18 +223,37 @@ public abstract class ProviderSession<T, R>
}
private void updateCandidateMetric(Status status) {
mCandidatePhasePerProviderMetric.setCandidateUid(mProviderSessionUid);
// TODO immediately update the candidate phase here to have more new data
mCandidatePhasePerProviderMetric
.setQueryFinishTimeNanoseconds(System.nanoTime());
if (isTerminatingStatus(status)) {
mCandidatePhasePerProviderMetric.setProviderQueryStatus(
ProviderStatusForMetrics.QUERY_FAILURE
.getMetricCode());
} else if (isCompletionStatus(status)) {
mCandidatePhasePerProviderMetric.setProviderQueryStatus(
ProviderStatusForMetrics.QUERY_SUCCESS
.getMetricCode());
try {
mCandidatePhasePerProviderMetric.setCandidateUid(mProviderSessionUid);
// TODO immediately update the candidate phase here to have more new data
mCandidatePhasePerProviderMetric
.setQueryFinishTimeNanoseconds(System.nanoTime());
if (isTerminatingStatus(status)) {
mCandidatePhasePerProviderMetric.setQueryReturned(false);
mCandidatePhasePerProviderMetric.setProviderQueryStatus(
ProviderStatusForMetrics.QUERY_FAILURE
.getMetricCode());
} else if (isCompletionStatus(status)) {
mCandidatePhasePerProviderMetric.setQueryReturned(true);
mCandidatePhasePerProviderMetric.setProviderQueryStatus(
ProviderStatusForMetrics.QUERY_SUCCESS
.getMetricCode());
}
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
// Common method to transfer metrics from the initial phase to the candidate phase per provider
protected void startCandidateMetrics() {
try {
InitialPhaseMetric initMetric = ((RequestSession) mCallbacks).mInitialPhaseMetric;
mCandidatePhasePerProviderMetric.setSessionId(initMetric.getSessionId());
mCandidatePhasePerProviderMetric.setServiceBeganTimeNanoseconds(
initMetric.getCredentialServiceStartedTimeNanoseconds());
mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}

View File

@@ -78,8 +78,8 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
protected final CancellationSignal mCancellationSignal;
protected final Map<String, ProviderSession> mProviders = new HashMap<>();
protected InitialPhaseMetric mInitialPhaseMetric = new InitialPhaseMetric();
protected ChosenProviderFinalPhaseMetric
protected final InitialPhaseMetric mInitialPhaseMetric = new InitialPhaseMetric();
protected final ChosenProviderFinalPhaseMetric
mChosenProviderFinalPhaseMetric = new ChosenProviderFinalPhaseMetric();
// TODO(b/271135048) - Group metrics used in a scope together, such as here in RequestSession
@@ -123,9 +123,17 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
mUserId, this);
mHybridService = context.getResources().getString(
R.string.config_defaultCredentialManagerHybridService);
mInitialPhaseMetric.setCredentialServiceStartedTimeNanoseconds(timestampStarted);
mInitialPhaseMetric.setSessionId(mRequestId.hashCode());
mInitialPhaseMetric.setCallerUid(mCallingUid);
initialPhaseMetricSetup(timestampStarted);
}
private void initialPhaseMetricSetup(long timestampStarted) {
try {
mInitialPhaseMetric.setCredentialServiceStartedTimeNanoseconds(timestampStarted);
mInitialPhaseMetric.setSessionId(mRequestId.hashCode());
mInitialPhaseMetric.setCallerUid(mCallingUid);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
public abstract ProviderSession initiateProviderSession(CredentialProviderInfo providerInfo,
@@ -170,13 +178,17 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
private void logBrowsingPhasePerSelect(UserSelectionDialogResult selection,
ProviderSession providerSession) {
CandidateBrowsingPhaseMetric browsingPhaseMetric = new CandidateBrowsingPhaseMetric();
browsingPhaseMetric.setSessionId(this.mInitialPhaseMetric.getSessionId());
browsingPhaseMetric.setEntryEnum(
EntryEnum.getMetricCodeFromString(selection.getEntryKey()));
browsingPhaseMetric.setProviderUid(providerSession.mCandidatePhasePerProviderMetric
.getCandidateUid());
this.mCandidateBrowsingPhaseMetric.add(new CandidateBrowsingPhaseMetric());
try {
CandidateBrowsingPhaseMetric browsingPhaseMetric = new CandidateBrowsingPhaseMetric();
browsingPhaseMetric.setSessionId(this.mInitialPhaseMetric.getSessionId());
browsingPhaseMetric.setEntryEnum(
EntryEnum.getMetricCodeFromString(selection.getEntryKey()));
browsingPhaseMetric.setProviderUid(providerSession.mCandidatePhasePerProviderMetric
.getCandidateUid());
this.mCandidateBrowsingPhaseMetric.add(new CandidateBrowsingPhaseMetric());
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
protected void finishSession(boolean propagateCancellation) {
@@ -233,6 +245,7 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
Log.i(TAG, "In getProviderDataAndInitiateUi providers size: " + mProviders.size());
if (isSessionCancelled()) {
MetricUtilities.logApiCalled(mProviders, ++mSequenceCounter);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -248,13 +261,8 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
}
if (!providerDataList.isEmpty()) {
Log.i(TAG, "provider list not empty about to initiate ui");
// TODO immediately Add paths to end it (say it fails)
if (isSessionCancelled()) {
Log.i(TAG, "In getProviderDataAndInitiateUi but session has been cancelled");
// TODO immedaitely Add paths
} else {
launchUiWithProviderData(providerDataList);
}
MetricUtilities.logApiCalled(mProviders, ++mSequenceCounter);
launchUiWithProviderData(providerDataList);
}
}
@@ -264,22 +272,27 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
* @param componentName the componentName to associate with a provider
*/
protected void setChosenMetric(ComponentName componentName) {
CandidatePhaseMetric metric = this.mProviders.get(componentName.flattenToString())
.mCandidatePhasePerProviderMetric;
try {
CandidatePhaseMetric metric = this.mProviders.get(componentName.flattenToString())
.mCandidatePhasePerProviderMetric;
mChosenProviderFinalPhaseMetric.setSessionId(metric.getSessionId());
mChosenProviderFinalPhaseMetric.setChosenUid(metric.getCandidateUid());
mChosenProviderFinalPhaseMetric.setSessionId(metric.getSessionId());
mChosenProviderFinalPhaseMetric.setChosenUid(metric.getCandidateUid());
mChosenProviderFinalPhaseMetric.setQueryPhaseLatencyMicroseconds(
metric.getQueryLatencyMicroseconds());
mChosenProviderFinalPhaseMetric.setQueryPhaseLatencyMicroseconds(
metric.getQueryLatencyMicroseconds());
mChosenProviderFinalPhaseMetric.setServiceBeganTimeNanoseconds(
metric.getServiceBeganTimeNanoseconds());
mChosenProviderFinalPhaseMetric.setQueryStartTimeNanoseconds(
metric.getStartQueryTimeNanoseconds());
mChosenProviderFinalPhaseMetric.setServiceBeganTimeNanoseconds(
metric.getServiceBeganTimeNanoseconds());
mChosenProviderFinalPhaseMetric.setQueryStartTimeNanoseconds(
metric.getStartQueryTimeNanoseconds());
// TODO immediately update with the entry count numbers from the candidate metrics
// TODO immediately update with the entry count numbers from the candidate metrics
// TODO immediately add the exception bit for candidates and providers
mChosenProviderFinalPhaseMetric.setFinalFinishTimeNanoseconds(System.nanoTime());
mChosenProviderFinalPhaseMetric.setFinalFinishTimeNanoseconds(System.nanoTime());
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
}
}
}

View File

@@ -20,6 +20,9 @@ import android.util.Log;
import com.android.server.credentials.MetricUtilities;
import java.util.ArrayList;
import java.util.List;
/**
* The central candidate provider metric object that mimics our defined metric setup.
* Some types are redundant across these metric collectors, but that has debug use-cases as
@@ -66,6 +69,8 @@ public class CandidatePhaseMetric {
private int mRemoteEntryCount = -1;
// The count of authentication entries from this provider, defaults to -1
private int mAuthenticationEntryCount = -1;
// Gathered to pass on to chosen provider when required
private List<EntryEnum> mAvailableEntries = new ArrayList<>();
public CandidatePhaseMetric() {
}
@@ -236,4 +241,28 @@ public class CandidatePhaseMetric {
public int getAuthenticationEntryCount() {
return mAuthenticationEntryCount;
}
/* -------------- The Entries Gathered ---------------- */
/**
* Allows adding an entry record to this metric collector, which can then be propagated to
* the final phase to retain information on the data available to the candidate.
*
* @param e the entry enum collected by the candidate provider associated with this metric
* collector
*/
public void addEntry(EntryEnum e) {
this.mAvailableEntries.add(e);
}
/**
* Returns a safely copied list of the entries captured by this metric collector associated
* with a particular candidate provider.
*
* @return the full collection of entries encountered by the candidate provider associated with
* this metric
*/
public List<EntryEnum> getAvailableEntries() {
return new ArrayList<>(this.mAvailableEntries); // no alias copy
}
}