Merge "Adding Final Phase Exception String to Logs" into udc-dev

This commit is contained in:
Arpan Kaphle
2023-05-08 19:02:17 +00:00
committed by Android (Google) Code Review
9 changed files with 91 additions and 38 deletions

View File

@@ -19,6 +19,7 @@ package com.android.server.credentials;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.credentials.ClearCredentialStateException;
import android.credentials.ClearCredentialStateRequest;
import android.credentials.CredentialProviderInfo;
import android.credentials.IClearCredentialStateCallback;
@@ -141,8 +142,9 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
return;
}
}
// TODO: Replace with properly defined error type
respondToClientWithErrorAndFinish("UNKNOWN", "All providers failed");
String exception = ClearCredentialStateException.TYPE_UNKNOWN;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception, "All providers failed");
}
@Override

View File

@@ -141,7 +141,9 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
} else {
mRequestSessionMetric.collectChosenProviderStatus(
ProviderStatusForMetrics.FINAL_FAILURE.getMetricCode());
respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREATE_OPTIONS,
String exception = CreateCredentialException.TYPE_NO_CREATE_OPTIONS;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"Invalid response");
}
}
@@ -154,18 +156,21 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
@Override
public void onUiCancellation(boolean isUserCancellation) {
if (isUserCancellation) {
respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_USER_CANCELED,
"User cancelled the selector");
} else {
respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_INTERRUPTED,
"The UI was interrupted - please try again.");
String exception = CreateCredentialException.TYPE_USER_CANCELED;
String message = "User cancelled the selector";
if (!isUserCancellation) {
exception = CreateCredentialException.TYPE_INTERRUPTED;
message = "The UI was interrupted - please try again.";
}
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception, message);
}
@Override
public void onUiSelectorInvocationFailure() {
respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREATE_OPTIONS,
String exception = CreateCredentialException.TYPE_NO_CREATE_OPTIONS;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"No create options available.");
}
@@ -181,7 +186,9 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
Slog.i(TAG, "Provider status changed - ui invocation is needed");
getProviderDataAndInitiateUi();
} else {
respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREATE_OPTIONS,
String exception = CreateCredentialException.TYPE_NO_CREATE_OPTIONS;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"No create options available.");
}
}

View File

@@ -106,8 +106,10 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
} catch (RemoteException e) {
mRequestSessionMetric.collectUiReturnedFinalPhase(/*uiReturned=*/ false);
mCredentialManagerUi.setStatus(CredentialManagerUi.UiStatus.TERMINATED);
String exception = GetCredentialException.TYPE_UNKNOWN;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(
GetCredentialException.TYPE_UNKNOWN, "Unable to instantiate selector");
exception, "Unable to instantiate selector");
}
}
@@ -138,7 +140,9 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
} else {
mRequestSessionMetric.collectChosenProviderStatus(
ProviderStatusForMetrics.FINAL_FAILURE.getMetricCode());
respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
String exception = GetCredentialException.TYPE_NO_CREDENTIAL;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"Invalid response from provider");
}
}
@@ -152,18 +156,21 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
@Override
public void onUiCancellation(boolean isUserCancellation) {
if (isUserCancellation) {
respondToClientWithErrorAndFinish(GetCredentialException.TYPE_USER_CANCELED,
"User cancelled the selector");
} else {
respondToClientWithErrorAndFinish(GetCredentialException.TYPE_INTERRUPTED,
"The UI was interrupted - please try again.");
String exception = GetCredentialException.TYPE_NO_CREDENTIAL;
String message = "User cancelled the selector";
if (!isUserCancellation) {
exception = GetCredentialException.TYPE_INTERRUPTED;
message = "The UI was interrupted - please try again.";
}
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception, message);
}
@Override
public void onUiSelectorInvocationFailure() {
respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
String exception = GetCredentialException.TYPE_NO_CREDENTIAL;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"No credentials available.");
}
@@ -187,7 +194,9 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
Slog.i(TAG, "Provider status changed - ui invocation is needed");
getProviderDataAndInitiateUi();
} else {
respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
String exception = GetCredentialException.TYPE_NO_CREDENTIAL;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"No credentials available");
}
}
@@ -208,7 +217,9 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
// Respond to client if all auth entries are empty and nothing else to show on the UI
if (providerDataContainsEmptyAuthEntriesOnly()) {
respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
String exception = GetCredentialException.TYPE_NO_CREDENTIAL;
mRequestSessionMetric.collectFrameworkException(exception);
respondToClientWithErrorAndFinish(exception,
"No credentials available");
}
}

View File

@@ -48,12 +48,15 @@ public class MetricUtilities {
public static final String DEFAULT_STRING = "";
public static final int[] DEFAULT_REPEATED_INT_32 = new int[0];
public static final String[] DEFAULT_REPEATED_STR = new String[0];
public static final boolean[] DEFAULT_REPEATED_BOOL = new boolean[0];
// Used for single count metric emits, such as singular amounts of various types
public static final int UNIT = 1;
// Used for zero count metric emits, such as zero amounts of various types
public static final int ZERO = 0;
// The number of characters at the end of the string to use as a key
public static final int DELTA_CUT = 20;
public static final int DELTA_RESPONSES_CUT = 20;
// The cut for exception strings from the end - used to keep metrics small
public static final int DELTA_EXCEPTION_CUT = 30;
/**
* This retrieves the uid of any package name, given a context and a component name for the
@@ -165,8 +168,10 @@ public class MetricUtilities {
finalPhaseMetric.getResponseCollective().getUniqueResponseStrings(),
/* per_classtype_counts */
finalPhaseMetric.getResponseCollective().getUniqueResponseCounts(),
/* framework_exception_unique_classtypes */
DEFAULT_STRING
/* framework_exception_unique_classtype */
finalPhaseMetric.getFrameworkException(),
/* primary_indicated */
false
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during final provider uid emit: " + e);
@@ -268,7 +273,9 @@ public class MetricUtilities {
/* per_classtype_counts */
initialPhaseMetric.getUniqueRequestCounts(),
/* api_name */
initialPhaseMetric.getApiName()
initialPhaseMetric.getApiName(),
/* primary_candidates_indicated */
DEFAULT_REPEATED_BOOL
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during candidate provider uid metric emit: " + e);

View File

@@ -209,7 +209,6 @@ public abstract class ProviderSession<T, R>
isCompletionStatus(status), mProviderSessionUid);
mCallbacks.onProviderStatusChanged(status, mComponentName, source);
}
/** Common method that transfers metrics from the init phase to candidates */
protected void startCandidateMetrics() {
mProviderSessionMetric.collectCandidateMetricSetupViaInitialMetric(

View File

@@ -53,6 +53,7 @@ public class CandidatePhaseMetric {
private int mProviderQueryStatus = -1;
// Indicates if an exception was thrown by this provider, false by default
private boolean mHasException = false;
// Indicates the framework only exception belonging to this provider
private String mFrameworkException = "";
// Stores the response credential information, as well as the response entry information which

View File

@@ -66,6 +66,8 @@ public class ChosenProviderFinalPhaseMetric {
private int mChosenProviderStatus = -1;
// Indicates if an exception was thrown by this provider, false by default
private boolean mHasException = false;
// Indicates a framework only exception that occurs in the final phase of the flow
private String mFrameworkException = "";
// Stores the response credential information, as well as the response entry information which
// by default, contains empty info
@@ -272,4 +274,14 @@ public class ChosenProviderFinalPhaseMetric {
public ResponseCollective getResponseCollective() {
return mResponseCollective;
}
/* -------------- Framework Exception ---------------- */
public void setFrameworkException(String frameworkException) {
mFrameworkException = frameworkException;
}
public String getFrameworkException() {
return mFrameworkException;
}
}

View File

@@ -16,7 +16,7 @@
package com.android.server.credentials.metrics;
import static com.android.server.credentials.MetricUtilities.DELTA_CUT;
import static com.android.server.credentials.MetricUtilities.DELTA_RESPONSES_CUT;
import static com.android.server.credentials.MetricUtilities.generateMetricKey;
import android.annotation.NonNull;
@@ -170,7 +170,7 @@ public class ProviderSessionMetric {
entryCounts.put(EntryEnum.AUTHENTICATION_ENTRY, numAuthEntries);
entries.forEach(entry -> {
String entryKey = generateMetricKey(entry.getType(), DELTA_CUT);
String entryKey = generateMetricKey(entry.getType(), DELTA_RESPONSES_CUT);
responseCounts.put(entryKey, responseCounts.getOrDefault(entryKey, 0) + 1);
});
@@ -212,7 +212,7 @@ public class ProviderSessionMetric {
entryCounts.put(EntryEnum.AUTHENTICATION_ENTRY, numAuthEntries);
response.getCredentialEntries().forEach(entry -> {
String entryKey = generateMetricKey(entry.getType(), DELTA_CUT);
String entryKey = generateMetricKey(entry.getType(), DELTA_RESPONSES_CUT);
responseCounts.put(entryKey, responseCounts.getOrDefault(entryKey, 0) + 1);
});

View File

@@ -16,7 +16,8 @@
package com.android.server.credentials.metrics;
import static com.android.server.credentials.MetricUtilities.DELTA_CUT;
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.logApiCalledCandidatePhase;
import static com.android.server.credentials.MetricUtilities.logApiCalledFinalPhase;
@@ -168,11 +169,9 @@ public class RequestSessionMetric {
Map<String, Integer> uniqueRequestCounts = new LinkedHashMap<>();
try {
request.getCredentialOptions().forEach(option -> {
String optionKey = generateMetricKey(option.getType(), DELTA_CUT);
if (!uniqueRequestCounts.containsKey(optionKey)) {
uniqueRequestCounts.put(optionKey, 0);
}
uniqueRequestCounts.put(optionKey, uniqueRequestCounts.get(optionKey) + 1);
String optionKey = generateMetricKey(option.getType(), DELTA_RESPONSES_CUT);
uniqueRequestCounts.put(optionKey, uniqueRequestCounts.getOrDefault(optionKey,
0) + 1);
});
} catch (Exception e) {
Slog.i(TAG, "Unexpected error during get request metric logging: " + e);
@@ -218,7 +217,7 @@ public class RequestSessionMetric {
}
/**
* Updates the final phase metric with the designated bit
* Updates the final phase metric with the designated bit.
*
* @param exceptionBitFinalPhase represents if the final phase provider had an exception
*/
@@ -230,6 +229,21 @@ public class RequestSessionMetric {
}
}
/**
* This allows collecting the framework exception string for the final phase metric.
* NOTE that this exception will be cut for space optimizations.
*
* @param exception the framework exception that is being recorded
*/
public void collectFrameworkException(String exception) {
try {
mChosenProviderFinalPhaseMetric.setFrameworkException(
generateMetricKey(exception, DELTA_EXCEPTION_CUT));
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
/**
* Allows encapsulating the overall final phase metric status from the chosen and final
* provider.
@@ -284,7 +298,7 @@ public class RequestSessionMetric {
* In the final phase, this helps log use cases that were either pure failures or user
* canceled. It's expected that {@link #collectFinalPhaseProviderMetricStatus(boolean,
* ProviderStatusForMetrics) collectFinalPhaseProviderMetricStatus} is called prior to this.
* Otherwise, the logging will miss required bits
* Otherwise, the logging will miss required bits.
*
* @param isUserCanceledError a boolean indicating if the error was due to user cancelling
*/