Handling sequential auth entries in metrics

Since auth entries could repeat multiple times, maybe across multiple
providers, this ensures that the aggregate and single case properly
handle such sequential amounts of calls and emit them accordingly.

Bug: 271135048
Test: Build and Won't Submit without E2E Test
Change-Id: If4b77e0865761c22bd2e63b333bd46647f25d976
This commit is contained in:
Arpan Kaphle
2023-05-03 18:54:59 +00:00
parent 39942cfa7e
commit 9cfa89f4ed
4 changed files with 44 additions and 26 deletions

View File

@@ -214,8 +214,7 @@ public class MetricUtilities {
public static void logApiCalledCandidateGetMetric(Map<String, ProviderSession> providers,
int emitSequenceId) {
try {
// TODO(immediately) - Modify to a Static Queue of Ordered Functions and emit from
// queue to adhere to 10 second limit (thread removed given android safe-calling).
// TODO(b/future) - Switch to Log format
var sessions = providers.values();
for (var session : sessions) {
try {
@@ -416,7 +415,7 @@ public class MetricUtilities {
/*session_id*/ candidateAggregateMetric.getSessionIdProvider(),
/*sequence_num*/ sequenceNum,
/*query_returned*/ candidateAggregateMetric.isQueryReturned(),
/*num_providers*/ candidateAggregateMetric.getNumProviders(),
/*num_query_providers*/ candidateAggregateMetric.getNumProviders(),
/*min_query_start_timestamp_microseconds*/
DEFAULT_INT_32,
/*max_query_end_timestamp_microseconds*/
@@ -440,13 +439,17 @@ public class MetricUtilities {
/*query_per_exception_classtype_counts*/
DEFAULT_REPEATED_INT_32,
/*auth_response_unique_classtypes*/
DEFAULT_REPEATED_STR,
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueResponseStrings(),
/*auth_per_classtype_counts*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueResponseCounts(),
/*auth_unique_entries*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueEntries(),
/*auth_per_entry_counts*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueEntryCounts(),
/*auth_total_candidate_failure*/
DEFAULT_INT_32,
/*auth_framework_exception_unique_classtypes*/
@@ -454,7 +457,7 @@ public class MetricUtilities {
/*auth_per_exception_classtype_counts*/
DEFAULT_REPEATED_INT_32,
/*num_auth_clicks*/
DEFAULT_INT_32,
candidateAggregateMetric.getNumAuthEntriesTapped(),
/*auth_returned*/ false
);
}

View File

@@ -59,7 +59,6 @@ public class CandidateAggregateMetric {
* @param providers the providers associated with the candidate flow
*/
public void collectAverages(Map<String, ProviderSession> providers) {
// TODO(b/271135048) : Complete this method
collectQueryAggregates(providers);
collectAuthAggregates(providers);
}
@@ -89,13 +88,16 @@ public class CandidateAggregateMetric {
var providerSessions = providers.values();
for (var session : providerSessions) {
var sessionMetric = session.getProviderSessionMetric();
var authMetric = sessionMetric.getBrowsedAuthenticationMetric();
mQueryReturned = mQueryReturned; // TODO add auth info
ResponseCollective authCollective = authMetric.getAuthEntryCollective();
ResponseCollective.combineTypeCountMaps(responseCountAuth,
authCollective.getResponseCountsMap());
ResponseCollective.combineTypeCountMaps(entryCountAuth,
authCollective.getEntryCountsMap());
var authMetrics = sessionMetric.getBrowsedAuthenticationMetric();
mQueryReturned = mQueryReturned; // TODO add rest of auth info
mNumAuthEntriesTapped += authMetrics.size();
for (var authMetric : authMetrics) {
ResponseCollective authCollective = authMetric.getAuthEntryCollective();
ResponseCollective.combineTypeCountMaps(responseCountAuth,
authCollective.getResponseCountsMap());
ResponseCollective.combineTypeCountMaps(entryCountAuth,
authCollective.getEntryCountsMap());
}
}
mAggregateCollectiveAuth = new ResponseCollective(responseCountAuth, entryCountAuth);
}
@@ -116,4 +118,8 @@ public class CandidateAggregateMetric {
public ResponseCollective getAggregateCollectiveQuery() {
return mAggregateCollectiveQuery;
}
public ResponseCollective getAggregateCollectiveAuth() {
return mAggregateCollectiveAuth;
}
}

View File

@@ -28,6 +28,7 @@ import android.util.Slog;
import com.android.server.credentials.MetricUtilities;
import com.android.server.credentials.metrics.shared.ResponseCollective;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -47,13 +48,17 @@ public class ProviderSessionMetric {
protected final CandidatePhaseMetric mCandidatePhasePerProviderMetric;
// IFF there was an authentication entry clicked, this stores all required information for
// that event. This is for the 'get' flow.
// that event. This is for the 'get' flow. Notice these flows may be repetitive.
// Thus each provider stores a list of authentication metrics. The time between emits
// of these metrics should exceed 10 ms (given human reaction time is ~ 100's of ms), so emits
// will never collide. However, for aggregation, this will store information accordingly.
@NonNull
protected final BrowsedAuthenticationMetric mBrowsedAuthenticationMetric;
protected final List<BrowsedAuthenticationMetric> mBrowsedAuthenticationMetric =
new ArrayList<>();
public ProviderSessionMetric(int sessionIdTrackTwo) {
mCandidatePhasePerProviderMetric = new CandidatePhaseMetric(sessionIdTrackTwo);
mBrowsedAuthenticationMetric = new BrowsedAuthenticationMetric(sessionIdTrackTwo);
mBrowsedAuthenticationMetric.add(new BrowsedAuthenticationMetric(sessionIdTrackTwo));
}
/**
@@ -66,7 +71,7 @@ public class ProviderSessionMetric {
/**
* Retrieves the authentication clicked metric information.
*/
public BrowsedAuthenticationMetric getBrowsedAuthenticationMetric() {
public List<BrowsedAuthenticationMetric> getBrowsedAuthenticationMetric() {
return mBrowsedAuthenticationMetric;
}
@@ -97,8 +102,10 @@ public class ProviderSessionMetric {
// TODO(b/271135048) - Mimic typical candidate update, but with authentication metric
// Collect the final timestamps (and start timestamp), status, exceptions and the provider
// uid. This occurs typically *after* the collection is complete.
mBrowsedAuthenticationMetric.setProviderUid(providerSessionUid);
// TODO(immediately) - add timestamps
var mostRecentAuthenticationMetric = mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
mostRecentAuthenticationMetric.setProviderUid(providerSessionUid);
// TODO(immediately) - add timestamps (no longer needed!!) but also update below values!
if (isFailureStatus) {
mCandidatePhasePerProviderMetric.setQueryReturned(false);
mCandidatePhasePerProviderMetric.setProviderQueryStatus(
@@ -259,7 +266,12 @@ public class ProviderSessionMetric {
if (!isAuthEntry) {
mCandidatePhasePerProviderMetric.setResponseCollective(responseCollective);
} else {
mBrowsedAuthenticationMetric.setAuthEntryCollective(responseCollective);
BrowsedAuthenticationMetric browsedAuthenticationMetric =
new BrowsedAuthenticationMetric(mCandidatePhasePerProviderMetric
.getSessionIdProvider());
// to receive an auth entry, the candidate phase must have succeeded
browsedAuthenticationMetric.setAuthEntryCollective(responseCollective);
mBrowsedAuthenticationMetric.add(browsedAuthenticationMetric);
}
}
}

View File

@@ -53,7 +53,6 @@ public class RequestSessionMetric {
protected final InitialPhaseMetric mInitialPhaseMetric;
protected final ChosenProviderFinalPhaseMetric
mChosenProviderFinalPhaseMetric;
// TODO(b/271135048) - Replace this with a new atom per each browsing emit (V4)
protected List<CandidateBrowsingPhaseMetric> mCandidateBrowsingPhaseMetric = new ArrayList<>();
// Specific aggregate candidate provider metric for the provider this session handles
@NonNull
@@ -216,8 +215,6 @@ public class RequestSessionMetric {
/**
* During browsing, where multiple entries can be selected, this collects the browsing phase
* metric information.
* TODO(b/271135048) - modify asap to account for a new metric emit per browse response to
* framework.
*
* @param selection contains the selected entry key type
* @param selectedProviderPhaseMetric contains the utility information of the selected provider