Merge changes I52efc7fd,I531c1be0,Ib3870fb1,I94e95ead,I72140e75 into udc-dev

* changes:
  Emit Simple Metrics for Set/GetCredProvider APIs
  Primary Info in Candidate Metric
  Adding isPrimary to Final Phase Metrics
  Setting up the emit of the aggregate phase
  Completely emitting aggr candidate+auth metrics
This commit is contained in:
Arpan Kaphle
2023-05-11 04:53:56 +00:00
committed by Android (Google) Code Review
14 changed files with 263 additions and 61 deletions

View File

@@ -30,8 +30,6 @@ import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
import android.util.Slog;
import com.android.server.credentials.metrics.ProviderSessionMetric;
import java.util.ArrayList;
import java.util.Set;
@@ -95,12 +93,8 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
public void onFinalResponseReceived(
ComponentName componentName,
Void response) {
if (mProviders.get(componentName.flattenToString()) != null) {
ProviderSessionMetric providerSessionMetric =
mProviders.get(componentName.flattenToString()).mProviderSessionMetric;
mRequestSessionMetric.collectChosenMetricViaCandidateTransfer(providerSessionMetric
.getCandidatePhasePerProviderMetric());
}
mRequestSessionMetric.updateMetricsOnResponseReceived(mProviders, componentName,
isPrimaryProviderViaProviderInfo(componentName));
respondToClientWithResponseAndFinish(null);
}

View File

@@ -35,7 +35,6 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.PermissionUtils;
import android.util.Slog;
import com.android.server.credentials.metrics.ProviderSessionMetric;
import com.android.server.credentials.metrics.ProviderStatusForMetrics;
import java.util.ArrayList;
@@ -132,12 +131,8 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
@Nullable CreateCredentialResponse response) {
Slog.i(TAG, "Final credential received from: " + componentName.flattenToString());
mRequestSessionMetric.collectUiResponseData(/*uiReturned=*/ true, System.nanoTime());
if (mProviders.get(componentName.flattenToString()) != null) {
ProviderSessionMetric providerSessionMetric =
mProviders.get(componentName.flattenToString()).mProviderSessionMetric;
mRequestSessionMetric.collectChosenMetricViaCandidateTransfer(providerSessionMetric
.getCandidatePhasePerProviderMetric());
}
mRequestSessionMetric.updateMetricsOnResponseReceived(mProviders, componentName,
isPrimaryProviderViaProviderInfo(componentName));
if (response != null) {
mRequestSessionMetric.collectChosenProviderStatus(
ProviderStatusForMetrics.FINAL_SUCCESS.getMetricCode());

View File

@@ -706,11 +706,18 @@ public final class CredentialManagerService
public void setEnabledProviders(
List<String> primaryProviders, List<String> providers, int userId,
ISetEnabledProvidersCallback callback) {
final int callingUid = Binder.getCallingUid();
if (!hasWriteSecureSettingsPermission()) {
try {
MetricUtilities.logApiCalledSimpleV2(
ApiName.SET_ENABLED_PROVIDERS,
ApiStatus.FAILURE, callingUid);
callback.onError(
PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
} catch (RemoteException e) {
MetricUtilities.logApiCalledSimpleV2(
ApiName.SET_ENABLED_PROVIDERS,
ApiStatus.FAILURE, callingUid);
Slog.e(TAG, "Issue with invoking response: ", e);
}
return;
@@ -744,10 +751,16 @@ public final class CredentialManagerService
if (!writeEnabledStatus || !writePrimaryStatus) {
Slog.e(TAG, "Failed to store setting containing enabled or primary providers");
try {
MetricUtilities.logApiCalledSimpleV2(
ApiName.SET_ENABLED_PROVIDERS,
ApiStatus.FAILURE, callingUid);
callback.onError(
"failed_setting_store",
"Failed to store setting containing enabled or primary providers");
} catch (RemoteException e) {
MetricUtilities.logApiCalledSimpleV2(
ApiName.SET_ENABLED_PROVIDERS,
ApiStatus.FAILURE, callingUid);
Slog.e(TAG, "Issue with invoking error response: ", e);
return;
}
@@ -755,8 +768,14 @@ public final class CredentialManagerService
// Call the callback.
try {
MetricUtilities.logApiCalledSimpleV2(
ApiName.SET_ENABLED_PROVIDERS,
ApiStatus.SUCCESS, callingUid);
callback.onResponse();
} catch (RemoteException e) {
MetricUtilities.logApiCalledSimpleV2(
ApiName.SET_ENABLED_PROVIDERS,
ApiStatus.FAILURE, callingUid);
Slog.e(TAG, "Issue with invoking response: ", e);
// TODO: Propagate failure
}
@@ -805,10 +824,15 @@ public final class CredentialManagerService
public List<CredentialProviderInfo> getCredentialProviderServices(
int userId, int providerFilter) {
verifyGetProvidersPermission();
final int callingUid = Binder.getCallingUid();
MetricUtilities.logApiCalledSimpleV2(
ApiName.GET_CREDENTIAL_PROVIDER_SERVICES,
ApiStatus.SUCCESS, callingUid);
return CredentialProviderInfoFactory
.getCredentialProviderServices(
mContext, userId, providerFilter, getEnabledProvidersForUser(userId),
getPrimaryProvidersForUserId(mContext, userId));
return CredentialProviderInfoFactory.getCredentialProviderServices(
mContext, userId, providerFilter, getEnabledProvidersForUser(userId),
getPrimaryProvidersForUserId(mContext, userId));
}
@Override

View File

@@ -34,7 +34,6 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.PermissionUtils;
import android.util.Slog;
import com.android.server.credentials.metrics.ProviderSessionMetric;
import com.android.server.credentials.metrics.ProviderStatusForMetrics;
import java.util.ArrayList;
@@ -134,13 +133,8 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
public void onFinalResponseReceived(ComponentName componentName,
@Nullable GetCredentialResponse response) {
Slog.i(TAG, "onFinalResponseReceived from: " + componentName.flattenToString());
mRequestSessionMetric.collectUiResponseData(/*uiReturned=*/ true, System.nanoTime());
if (mProviders.get(componentName.flattenToString()) != null) {
ProviderSessionMetric providerSessionMetric =
mProviders.get(componentName.flattenToString()).mProviderSessionMetric;
mRequestSessionMetric.collectChosenMetricViaCandidateTransfer(providerSessionMetric
.getCandidatePhasePerProviderMetric());
}
mRequestSessionMetric.updateMetricsOnResponseReceived(mProviders, componentName,
isPrimaryProviderViaProviderInfo(componentName));
if (response != null) {
mRequestSessionMetric.collectChosenProviderStatus(
ProviderStatusForMetrics.FINAL_SUCCESS.getMetricCode());

View File

@@ -103,6 +103,10 @@ public class MetricUtilities {
if (t2 - t1 > Integer.MAX_VALUE) {
throw new ArithmeticException("Input timestamps are too far apart and unsupported");
}
if (t2 < t1) {
Slog.i(TAG, "The timestamps aren't in expected order, falling back to default int");
return DEFAULT_INT_32;
}
return (int) ((t2 - t1) / 1000);
}
@@ -184,7 +188,7 @@ public class MetricUtilities {
finalPhaseMetric.getResponseCollective().getUniqueResponseCounts(),
/* framework_exception_unique_classtype */
finalPhaseMetric.getFrameworkException(),
/* primary_indicated */ false
/* primary_indicated */ finalPhaseMetric.isPrimary()
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during final provider uid emit: " + e);
@@ -222,7 +226,7 @@ public class MetricUtilities {
/* auth_provider_status */
authenticationMetric.getProviderStatus(),
/* query_returned */
authenticationMetric.isQueryReturned()
authenticationMetric.isAuthReturned()
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during candidate get metric logging: " + e);
@@ -303,6 +307,7 @@ public class MetricUtilities {
int[] candidateAuthEntryCountList = new int[providerSize];
int[] candidateRemoteEntryCountList = new int[providerSize];
String[] frameworkExceptionList = new String[providerSize];
boolean[] candidatePrimaryProviderList = new boolean[providerSize];
int index = 0;
for (var session : providerSessions) {
CandidatePhaseMetric metric = session.mProviderSessionMetric
@@ -335,6 +340,7 @@ public class MetricUtilities {
candidateRemoteEntryCountList[index] = metric.getResponseCollective()
.getCountForEntry(EntryEnum.REMOTE_ENTRY);
frameworkExceptionList[index] = metric.getFrameworkException();
candidatePrimaryProviderList[index] = metric.isPrimary();
index++;
}
FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_CANDIDATE_PHASE_REPORTED,
@@ -368,7 +374,7 @@ public class MetricUtilities {
/* api_name */
initialPhaseMetric.getApiName(),
/* primary_candidates_indicated */
DEFAULT_REPEATED_BOOL
candidatePrimaryProviderList
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during candidate provider uid metric emit: " + e);
@@ -450,9 +456,13 @@ public class MetricUtilities {
/*query_returned*/ candidateAggregateMetric.isQueryReturned(),
/*num_query_providers*/ candidateAggregateMetric.getNumProviders(),
/*min_query_start_timestamp_microseconds*/
DEFAULT_INT_32,
getMetricTimestampDifferenceMicroseconds(
candidateAggregateMetric.getMinProviderTimestampNanoseconds(),
candidateAggregateMetric.getServiceBeganTimeNanoseconds()),
/*max_query_end_timestamp_microseconds*/
DEFAULT_INT_32,
getMetricTimestampDifferenceMicroseconds(
candidateAggregateMetric.getMaxProviderTimestampNanoseconds(),
candidateAggregateMetric.getServiceBeganTimeNanoseconds()),
/*query_response_unique_classtypes*/
candidateAggregateMetric.getAggregateCollectiveQuery()
.getUniqueResponseStrings(),
@@ -466,11 +476,11 @@ public class MetricUtilities {
candidateAggregateMetric.getAggregateCollectiveQuery()
.getUniqueEntryCounts(),
/*query_total_candidate_failure*/
DEFAULT_INT_32,
candidateAggregateMetric.getTotalQueryFailures(),
/*query_framework_exception_unique_classtypes*/
DEFAULT_REPEATED_STR,
candidateAggregateMetric.getUniqueExceptionStringsQuery(),
/*query_per_exception_classtype_counts*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getUniqueExceptionCountsQuery(),
/*auth_response_unique_classtypes*/
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueResponseStrings(),
@@ -484,14 +494,15 @@ public class MetricUtilities {
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueEntryCounts(),
/*auth_total_candidate_failure*/
DEFAULT_INT_32,
candidateAggregateMetric.getTotalAuthFailures(),
/*auth_framework_exception_unique_classtypes*/
DEFAULT_REPEATED_STR,
candidateAggregateMetric.getUniqueExceptionStringsAuth(),
/*auth_per_exception_classtype_counts*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getUniqueExceptionCountsAuth(),
/*num_auth_clicks*/
candidateAggregateMetric.getNumAuthEntriesTapped(),
/*auth_returned*/ false
/*auth_returned*/
candidateAggregateMetric.isAuthReturned()
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during metric logging: " + e);
@@ -556,7 +567,7 @@ public class MetricUtilities {
/* clicked_entries */ browsedClickedEntries,
/* provider_of_clicked_entry */ browsedProviderUid,
/* api_status */ apiStatus,
/* primary_indicated */ false
/* primary_indicated */ finalPhaseMetric.isPrimary()
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during metric logging: " + e);

View File

@@ -214,9 +214,11 @@ public abstract class ProviderSession<T, R>
protected void updateStatusAndInvokeCallback(@NonNull Status status,
CredentialsSource source) {
setStatus(status);
boolean isPrimary = mProviderInfo != null && mProviderInfo.isPrimary();
mProviderSessionMetric.collectCandidateMetricUpdate(isTerminatingStatus(status),
isCompletionStatus(status), mProviderSessionUid,
source == CredentialsSource.AUTH_ENTRY);
/*isAuthEntry*/source == CredentialsSource.AUTH_ENTRY,
/*isPrimary*/isPrimary);
mCallbacks.onProviderStatusChanged(status, mComponentName, source);
}
/** Common method that transfers metrics from the init phase to candidates */

View File

@@ -304,6 +304,7 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
* @param response the response associated with the API call that just completed
*/
protected void respondToClientWithResponseAndFinish(V response) {
mRequestSessionMetric.logCandidateAggregateMetrics(mProviders);
mRequestSessionMetric.collectFinalPhaseProviderMetricStatus(/*has_exception=*/ false,
ProviderStatusForMetrics.FINAL_SUCCESS);
if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
@@ -337,6 +338,7 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
* @param errorMsg the error message given back in the flow
*/
protected void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
mRequestSessionMetric.logCandidateAggregateMetrics(mProviders);
mRequestSessionMetric.collectFinalPhaseProviderMetricStatus(
/*has_exception=*/ true, ProviderStatusForMetrics.FINAL_FAILURE);
if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
@@ -359,4 +361,16 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
mRequestSessionMetric.logFailureOrUserCancel(isUserCanceled);
finishSession(/*propagateCancellation=*/false);
}
/**
* Reveals if a certain provider is primary after ensuring it exists at all in the designated
* provider info.
*
* @param componentName used to identify the provider we want to check primary status for
*/
protected boolean isPrimaryProviderViaProviderInfo(ComponentName componentName) {
var chosenProviderSession = mProviders.get(componentName.flattenToString());
return chosenProviderSession != null && chosenProviderSession.mProviderInfo != null
&& chosenProviderSession.mProviderInfo.isPrimary();
}
}

View File

@@ -24,8 +24,11 @@ import static android.credentials.ui.RequestInfo.TYPE_UNDEFINED;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_CREATE_CREDENTIAL;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL_PROVIDER_SERVICES;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL_VIA_REGISTRY;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_REGISTER_CREDENTIAL_DESCRIPTION;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_SET_ENABLED_PROVIDERS;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_UNKNOWN;
import android.credentials.ui.RequestInfo;
@@ -45,6 +48,20 @@ CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL_VIA
CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_CLEAR_CREDENTIAL),
IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE(
CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE
),
SET_ENABLED_PROVIDERS(
CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_SET_ENABLED_PROVIDERS),
GET_CREDENTIAL_PROVIDER_SERVICES(
CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL_PROVIDER_SERVICES),
REGISTER_CREDENTIAL_DESCRIPTION(
CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_REGISTER_CREDENTIAL_DESCRIPTION
),
UNREGISTER_CREDENTIAL_DESCRIPTION(
CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_REGISTER_CREDENTIAL_DESCRIPTION
);
private static final String TAG = "ApiName";

View File

@@ -25,10 +25,9 @@ import java.util.Map;
* Contains information about what was collected from the authentication entry output.
*/
public class BrowsedAuthenticationMetric {
private static final String TAG = "BrowsedAuthenticationMetric";
private static final String TAG = "AuthenticationMetric";
// The session id of this provider known flow related metric
private final int mSessionIdProvider;
// The provider associated with the press, defaults to -1
private int mProviderUid = -1;
@@ -42,7 +41,7 @@ public class BrowsedAuthenticationMetric {
// The status of this particular provider
private int mProviderStatus = -1;
// Indicates if this provider returned from the authentication entry query, default false
private boolean mQueryReturned = false;
private boolean mAuthReturned = false;
// TODO(b/271135048) - Match the atom and provide a clean per provider session metric
// encapsulation.
@@ -84,12 +83,12 @@ public class BrowsedAuthenticationMetric {
mProviderStatus = providerStatus;
}
public void setQueryReturned(boolean queryReturned) {
mQueryReturned = queryReturned;
public void setAuthReturned(boolean authReturned) {
mAuthReturned = authReturned;
}
public boolean isQueryReturned() {
return mQueryReturned;
public boolean isAuthReturned() {
return mAuthReturned;
}
public int getProviderStatus() {

View File

@@ -24,7 +24,8 @@ import java.util.Map;
/**
* This will generate most of its data via using the information of {@link CandidatePhaseMetric}
* across all the providers. This belongs to the metric flow where the calling app is known.
* across all the providers. This belongs to the metric flow where the calling app is known. It
* also contains {@link BrowsedAuthenticationMetric} data aggregated within.
*/
public class CandidateAggregateMetric {
@@ -34,6 +35,9 @@ public class CandidateAggregateMetric {
// Indicates if this provider returned from the candidate query phase,
// true if at least one provider returns validly, even if empty, default false
private boolean mQueryReturned = false;
// For reference, the initial log timestamp when the service started running the API call,
// defaults to -1
private long mServiceBeganTimeNanoseconds = -1;
// Indicates the total number of providers this aggregate captures information for, default 0
private int mNumProviders = 0;
// Indicates if the authentication entry returned, true if at least one entry returns validly,
@@ -47,6 +51,18 @@ public class CandidateAggregateMetric {
// The combined aggregate collective across the auth entry info
private ResponseCollective mAggregateCollectiveAuth =
new ResponseCollective(Map.of(), Map.of());
// The minimum of all the providers query start time, defaults to -1
private long mMinProviderTimestampNanoseconds = -1;
// The maximum of all the providers query finish time, defaults to -1
private long mMaxProviderTimestampNanoseconds = -1;
// The total number of failures across all the providers, defaults to 0
private int mTotalQueryFailures = 0;
// The map of all seen framework exceptions and their counts across all providers, default empty
private Map<String, Integer> mExceptionCountQuery = new LinkedHashMap<>();
// The total number of failures across all auth entries, defaults to 0
private int mTotalAuthFailures = 0;
// The map of all seen framework exceptions and their counts across auth entries, default empty
private Map<String, Integer> mExceptionCountAuth = new LinkedHashMap<>();
public CandidateAggregateMetric(int sessionIdTrackOne) {
mSessionIdProvider = sessionIdTrackOne;
@@ -72,16 +88,33 @@ public class CandidateAggregateMetric {
Map<String, Integer> responseCountQuery = new LinkedHashMap<>();
Map<EntryEnum, Integer> entryCountQuery = new LinkedHashMap<>();
var providerSessions = providers.values();
long min_query_start = Integer.MAX_VALUE;
long max_query_end = Integer.MIN_VALUE;
for (var session : providerSessions) {
var sessionMetric = session.getProviderSessionMetric();
var candidateMetric = sessionMetric.getCandidatePhasePerProviderMetric();
if (mServiceBeganTimeNanoseconds == -1) {
mServiceBeganTimeNanoseconds = candidateMetric.getServiceBeganTimeNanoseconds();
}
mQueryReturned = mQueryReturned || candidateMetric.isQueryReturned();
ResponseCollective candidateCollective = candidateMetric.getResponseCollective();
ResponseCollective.combineTypeCountMaps(responseCountQuery,
candidateCollective.getResponseCountsMap());
ResponseCollective.combineTypeCountMaps(entryCountQuery,
candidateCollective.getEntryCountsMap());
min_query_start = Math.min(min_query_start,
candidateMetric.getStartQueryTimeNanoseconds());
max_query_end = Math.max(max_query_end, candidateMetric
.getQueryFinishTimeNanoseconds());
mTotalQueryFailures += (candidateMetric.isHasException() ? 1 : 0);
if (!candidateMetric.getFrameworkException().isEmpty()) {
mExceptionCountQuery.put(candidateMetric.getFrameworkException(),
mExceptionCountQuery.getOrDefault(
candidateMetric.getFrameworkException(), 0) + 1);
}
}
mMinProviderTimestampNanoseconds = min_query_start;
mMaxProviderTimestampNanoseconds = max_query_end;
mAggregateCollectiveQuery = new ResponseCollective(responseCountQuery, entryCountQuery);
}
@@ -95,12 +128,18 @@ public class CandidateAggregateMetric {
var authMetrics = sessionMetric.getBrowsedAuthenticationMetric();
mNumAuthEntriesTapped += authMetrics.size();
for (var authMetric : authMetrics) {
mAuthReturned = mAuthReturned || authMetric.isQueryReturned();
mAuthReturned = mAuthReturned || authMetric.isAuthReturned();
ResponseCollective authCollective = authMetric.getAuthEntryCollective();
ResponseCollective.combineTypeCountMaps(responseCountAuth,
authCollective.getResponseCountsMap());
ResponseCollective.combineTypeCountMaps(entryCountAuth,
authCollective.getEntryCountsMap());
mTotalQueryFailures += (authMetric.isHasException() ? 1 : 0);
if (!authMetric.getFrameworkException().isEmpty()) {
mExceptionCountQuery.put(authMetric.getFrameworkException(),
mExceptionCountQuery.getOrDefault(
authMetric.getFrameworkException(), 0) + 1);
}
}
}
mAggregateCollectiveAuth = new ResponseCollective(responseCountAuth, entryCountAuth);
@@ -130,4 +169,67 @@ public class CandidateAggregateMetric {
public boolean isAuthReturned() {
return mAuthReturned;
}
public long getMaxProviderTimestampNanoseconds() {
return mMaxProviderTimestampNanoseconds;
}
public long getMinProviderTimestampNanoseconds() {
return mMinProviderTimestampNanoseconds;
}
public int getTotalQueryFailures() {
return mTotalQueryFailures;
}
/**
* Returns the unique, deduped, exception classtypes for logging associated with this provider.
*
* @return a string array for deduped exception classtypes
*/
public String[] getUniqueExceptionStringsQuery() {
String[] result = new String[mExceptionCountQuery.keySet().size()];
mExceptionCountQuery.keySet().toArray(result);
return result;
}
/**
* Returns the unique, deduped, exception classtype counts for logging associated with this
* provider.
*
* @return a string array for deduped classtype exception counts
*/
public int[] getUniqueExceptionCountsQuery() {
return mExceptionCountQuery.values().stream().mapToInt(Integer::intValue).toArray();
}
/**
* Returns the unique, deduped, exception classtypes for logging associated with this provider
* for auth entries.
*
* @return a string array for deduped exception classtypes for auth entries
*/
public String[] getUniqueExceptionStringsAuth() {
String[] result = new String[mExceptionCountAuth.keySet().size()];
mExceptionCountAuth.keySet().toArray(result);
return result;
}
/**
* Returns the unique, deduped, exception classtype counts for logging associated with this
* provider for auth entries.
*
* @return a string array for deduped classtype exception counts for auth entries
*/
public int[] getUniqueExceptionCountsAuth() {
return mExceptionCountAuth.values().stream().mapToInt(Integer::intValue).toArray();
}
public long getServiceBeganTimeNanoseconds() {
return mServiceBeganTimeNanoseconds;
}
public int getTotalAuthFailures() {
return mTotalAuthFailures;
}
}

View File

@@ -59,6 +59,8 @@ public class CandidatePhaseMetric {
// Stores the response credential information, as well as the response entry information which
// by default, contains empty info
private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of());
// Indicates if this candidate is a primary provider, false by default
private boolean mIsPrimary = false;
public CandidatePhaseMetric(int sessionIdTrackTwo) {
mSessionIdProvider = sessionIdTrackTwo;
@@ -185,4 +187,12 @@ public class CandidatePhaseMetric {
public String getFrameworkException() {
return mFrameworkException;
}
public void setPrimary(boolean primary) {
mIsPrimary = primary;
}
public boolean isPrimary() {
return mIsPrimary;
}
}

View File

@@ -76,6 +76,8 @@ public class ChosenProviderFinalPhaseMetric {
// Stores the response credential information, as well as the response entry information which
// by default, contains empty info
private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of());
// Indicates if this chosen provider was the primary provider, false by default
private boolean mIsPrimary = false;
public ChosenProviderFinalPhaseMetric(int sessionIdCaller, int sessionIdProvider) {
@@ -292,4 +294,12 @@ public class ChosenProviderFinalPhaseMetric {
public int getSessionIdCaller() {
return mSessionIdCaller;
}
public void setPrimary(boolean primary) {
mIsPrimary = primary;
}
public boolean isPrimary() {
return mIsPrimary;
}
}

View File

@@ -100,8 +100,8 @@ public class ProviderSessionMetric {
*/
public void collectAuthenticationExceptionStatus(boolean hasException) {
try {
var mostRecentAuthenticationMetric = mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
BrowsedAuthenticationMetric mostRecentAuthenticationMetric =
getUsedAuthenticationMetric();
mostRecentAuthenticationMetric.setHasException(hasException);
} catch (Exception e) {
Slog.i(TAG, "Error while setting authentication metric exception " + e);
@@ -122,40 +122,44 @@ public class ProviderSessionMetric {
private void collectAuthEntryUpdate(boolean isFailureStatus,
boolean isCompletionStatus, int providerSessionUid) {
// 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.
var mostRecentAuthenticationMetric = mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
BrowsedAuthenticationMetric mostRecentAuthenticationMetric =
getUsedAuthenticationMetric();
mostRecentAuthenticationMetric.setProviderUid(providerSessionUid);
// TODO(immediately) - add timestamps (no longer needed!!) but also update below values!
if (isFailureStatus) {
mostRecentAuthenticationMetric.setQueryReturned(false);
mostRecentAuthenticationMetric.setAuthReturned(false);
mostRecentAuthenticationMetric.setProviderStatus(
ProviderStatusForMetrics.QUERY_FAILURE
.getMetricCode());
} else if (isCompletionStatus) {
mostRecentAuthenticationMetric.setQueryReturned(true);
mostRecentAuthenticationMetric.setAuthReturned(true);
mostRecentAuthenticationMetric.setProviderStatus(
ProviderStatusForMetrics.QUERY_SUCCESS
.getMetricCode());
}
}
private BrowsedAuthenticationMetric getUsedAuthenticationMetric() {
return mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
}
/**
* Used to collect metrics at the update stage when a candidate provider gives back an update.
*
* @param isFailureStatus indicates the candidate provider sent back a terminated response
* @param isCompletionStatus indicates the candidate provider sent back a completion response
* @param providerSessionUid the uid of the provider
* @param isPrimary indicates if this candidate provider was the primary provider
*/
public void collectCandidateMetricUpdate(boolean isFailureStatus,
boolean isCompletionStatus, int providerSessionUid, boolean isAuthEntry) {
boolean isCompletionStatus, int providerSessionUid, boolean isAuthEntry,
boolean isPrimary) {
try {
if (isAuthEntry) {
collectAuthEntryUpdate(isFailureStatus, isCompletionStatus, providerSessionUid);
return;
}
mCandidatePhasePerProviderMetric.setPrimary(isPrimary);
mCandidatePhasePerProviderMetric.setCandidateUid(providerSessionUid);
mCandidatePhasePerProviderMetric
.setQueryFinishTimeNanoseconds(System.nanoTime());

View File

@@ -20,6 +20,7 @@ import static com.android.server.credentials.MetricUtilities.DEFAULT_INT_32;
import static com.android.server.credentials.MetricUtilities.DELTA_EXCEPTION_CUT;
import static com.android.server.credentials.MetricUtilities.DELTA_RESPONSES_CUT;
import static com.android.server.credentials.MetricUtilities.generateMetricKey;
import static com.android.server.credentials.MetricUtilities.logApiCalledAggregateCandidate;
import static com.android.server.credentials.MetricUtilities.logApiCalledAuthenticationMetric;
import static com.android.server.credentials.MetricUtilities.logApiCalledCandidateGetMetric;
import static com.android.server.credentials.MetricUtilities.logApiCalledCandidatePhase;
@@ -27,6 +28,7 @@ import static com.android.server.credentials.MetricUtilities.logApiCalledFinalPh
import static com.android.server.credentials.MetricUtilities.logApiCalledNoUidFinal;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.credentials.GetCredentialRequest;
import android.credentials.ui.UserSelectionDialogResult;
import android.util.Slog;
@@ -279,6 +281,26 @@ public class RequestSessionMetric {
}
}
/**
* Used to update metrics when a response is received in a RequestSession.
*
* @param componentName the component name associated with the provider the response is for
*/
public void updateMetricsOnResponseReceived(Map<String, ProviderSession> providers,
ComponentName componentName, boolean isPrimary) {
try {
var chosenProviderSession = providers.get(componentName.flattenToString());
if (chosenProviderSession != null) {
ProviderSessionMetric providerSessionMetric =
chosenProviderSession.getProviderSessionMetric();
collectChosenMetricViaCandidateTransfer(providerSessionMetric
.getCandidatePhasePerProviderMetric(), isPrimary);
}
} catch (Exception e) {
Slog.i(TAG, "Exception upon candidate to chosen metric transfer: " + e);
}
}
/**
* Called by RequestSessions upon chosen metric determination. It's expected that most bits
* are transferred here. However, certain new information, such as the selected provider's final
@@ -288,10 +310,13 @@ public class RequestSessionMetric {
* {@link com.android.internal.util.FrameworkStatsLog} metric generation.
*
* @param candidatePhaseMetric the componentName to associate with a provider
* @param isPrimary indicates that this chosen provider is the primary provider (or not)
*/
public void collectChosenMetricViaCandidateTransfer(CandidatePhaseMetric candidatePhaseMetric) {
public void collectChosenMetricViaCandidateTransfer(CandidatePhaseMetric candidatePhaseMetric,
boolean isPrimary) {
try {
mChosenProviderFinalPhaseMetric.setChosenUid(candidatePhaseMetric.getCandidateUid());
mChosenProviderFinalPhaseMetric.setPrimary(isPrimary);
mChosenProviderFinalPhaseMetric.setQueryPhaseLatencyMicroseconds(
candidatePhaseMetric.getQueryLatencyMicroseconds());
@@ -357,6 +382,7 @@ public class RequestSessionMetric {
public void logCandidateAggregateMetrics(Map<String, ProviderSession> providers) {
try {
mCandidateAggregateMetric.collectAverages(providers);
logApiCalledAggregateCandidate(mCandidateAggregateMetric, ++mSequenceCounter);
} catch (Exception e) {
Slog.i(TAG, "Unexpected error during aggregate candidate logging " + e);
}