summaryrefslogtreecommitdiff
path: root/services/credentials/java
diff options
context:
space:
mode:
author Arpan Kaphle <akaphle@google.com> 2023-03-10 01:29:12 +0000
committer Arpan Kaphle <akaphle@google.com> 2023-03-15 02:06:13 +0000
commit99e42a3ed87d44472226b2e2f8c2717dd4e5618c (patch)
treea813d2ec6070970bdda089e10f0bbe46af870b82 /services/credentials/java
parent251260206a123428b4084a82912a82cc1871c146 (diff)
Candidate Metric Utilized in Framework
This adds the candidate metric in the framework at various places and goes up to emits, with TODOs left for the actual emits once the atoms build as expected. Bug: 270403549 Test: Builds for now Change-Id: I1196dbf0a5d6d5c6573d5f8dbde15dc3bc916f86
Diffstat (limited to 'services/credentials/java')
-rw-r--r--services/credentials/java/com/android/server/credentials/CreateRequestSession.java2
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java10
-rw-r--r--services/credentials/java/com/android/server/credentials/MetricUtilities.java30
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderClearSession.java17
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderCreateSession.java43
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderGetSession.java59
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderSession.java56
-rw-r--r--services/credentials/java/com/android/server/credentials/RequestSession.java80
-rw-r--r--services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java29
9 files changed, 233 insertions, 93 deletions
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 793d83e90cfe..4f8235a11b2a 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -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;
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 10d3dc030362..3f1a568cce51 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -580,9 +580,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
diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
index ed139b57da3d..99f3b3efe838 100644
--- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java
+++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
@@ -81,6 +81,34 @@ public class MetricUtilities {
}
/**
+ * 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
* on the situation, as this is geared towards the logging of {@link ProviderSession} types.
@@ -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
diff --git a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
index 950cf4f9a482..b86dabaa8503 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
@@ -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);
}
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 3ec0fc0d4646..bbbb15666028 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -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
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index ec8bf22e4514..bf1db373446b 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -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())
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 77d4e7750038..faa91dce7b92 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -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);
}
}
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index ed42bb2f010a..3ac10c9a7d22 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -19,7 +19,6 @@ package com.android.server.credentials;
import static com.android.server.credentials.MetricUtilities.logApiCalled;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
@@ -79,14 +78,14 @@ 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
// TODO(b/271135048) - Replace this with a new atom per each browsing emit (V4)
- @Nullable
- protected List<CandidateBrowsingPhaseMetric> mCandidateBrowsingPhaseMetric;
+ @NonNull
+ protected List<CandidateBrowsingPhaseMetric> mCandidateBrowsingPhaseMetric = new ArrayList<>();
// As emits occur in sequential order, increment this counter and utilize
protected int mSequenceCounter = 0;
protected final String mHybridService;
@@ -124,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,
@@ -171,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) {
@@ -234,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;
}
@@ -249,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);
}
}
@@ -265,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);
+ }
}
}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java
index c392d7806910..f00c7f46c5ae 100644
--- a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java
+++ b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java
@@ -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
+ }
}