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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user