Merge "Adding Final Phase {Deduped:Count} Objects" into udc-dev

This commit is contained in:
Arpan Kaphle
2023-04-30 19:25:15 +00:00
committed by Android (Google) Code Review
8 changed files with 241 additions and 292 deletions

View File

@@ -58,7 +58,6 @@ import android.provider.Settings;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfoFactory;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -472,7 +471,7 @@ public final class CredentialManagerService
GetCredentialException.TYPE_NO_CREDENTIAL,
"No credentials available on this device.");
} catch (RemoteException e) {
Log.i(
Slog.i(
TAG,
"Issue invoking onError on IGetCredentialCallback "
+ "callback: "
@@ -528,7 +527,7 @@ public final class CredentialManagerService
false, null,
false, false, null));
} catch (RemoteException e) {
Log.i(
Slog.i(
TAG,
"Issue invoking onError on IGetCredentialCallback "
+ "callback: "
@@ -673,7 +672,7 @@ public final class CredentialManagerService
MetricUtilities.logApiCalledInitialPhase(initMetric,
session.mRequestSessionMetric.returnIncrementSequence());
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: ", e);
Slog.w(TAG, "Unexpected error during metric logging: ", e);
}
}
@@ -706,7 +705,7 @@ public final class CredentialManagerService
Settings.Secure.CREDENTIAL_SERVICE,
storedValue,
userId)) {
Log.e(TAG, "Failed to store setting containing enabled providers");
Slog.e(TAG, "Failed to store setting containing enabled providers");
try {
callback.onError(
"failed_setting_store",
@@ -962,7 +961,7 @@ public final class CredentialManagerService
@Override
@GuardedBy("mLock")
public void onFinishRequestSession(@UserIdInt int userId, IBinder token) {
Log.i(TAG, "In onFinishRequestSession");
Slog.i(TAG, "In onFinishRequestSession");
if (mRequestSessions.get(userId) != null) {
mRequestSessions.get(userId).remove(token);
}

View File

@@ -19,7 +19,7 @@ package com.android.server.credentials;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
import android.util.Slog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.credentials.metrics.ApiName;
@@ -27,6 +27,7 @@ import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.credentials.metrics.CandidateBrowsingPhaseMetric;
import com.android.server.credentials.metrics.CandidatePhaseMetric;
import com.android.server.credentials.metrics.ChosenProviderFinalPhaseMetric;
import com.android.server.credentials.metrics.EntryEnum;
import com.android.server.credentials.metrics.InitialPhaseMetric;
import java.util.List;
@@ -69,7 +70,7 @@ public class MetricUtilities {
componentName.getPackageName(),
PackageManager.ApplicationInfoFlags.of(0)).uid;
} catch (Throwable t) {
Log.i(TAG, "Couldn't find required uid");
Slog.i(TAG, "Couldn't find required uid");
}
return sessUid;
}
@@ -147,28 +148,28 @@ public class MetricUtilities {
.getFinalFinishTimeNanoseconds()),
/* chosen_provider_status */ finalPhaseMetric.getChosenProviderStatus(),
/* chosen_provider_has_exception */ finalPhaseMetric.isHasException(),
/* chosen_provider_available_entries */ finalPhaseMetric.getAvailableEntries()
.stream().mapToInt(i -> i).toArray(),
/* chosen_provider_action_entry_count */ finalPhaseMetric.getActionEntryCount(),
/* chosen_provider_credential_entry_count */
finalPhaseMetric.getCredentialEntryCount(),
/* chosen_provider_credential_entry_type_count */
finalPhaseMetric.getCredentialEntryTypeCount(),
/* chosen_provider_remote_entry_count */
finalPhaseMetric.getRemoteEntryCount(),
/* chosen_provider_authentication_entry_count */
finalPhaseMetric.getAuthenticationEntryCount(),
/* chosen_provider_available_entries (deprecated) */ DEFAULT_REPEATED_INT_32,
/* chosen_provider_action_entry_count (deprecated) */ DEFAULT_INT_32,
/* chosen_provider_credential_entry_count (deprecated)*/DEFAULT_INT_32,
/* chosen_provider_credential_entry_type_count (deprecated) */ DEFAULT_INT_32,
/* chosen_provider_remote_entry_count (deprecated) */ DEFAULT_INT_32,
/* chosen_provider_authentication_entry_count (deprecated) */ DEFAULT_INT_32,
/* clicked_entries */ browsedClickedEntries,
/* provider_of_clicked_entry */ browsedProviderUid,
/* api_status */ apiStatus,
DEFAULT_REPEATED_INT_32,
DEFAULT_REPEATED_INT_32,
DEFAULT_REPEATED_STR,
DEFAULT_REPEATED_INT_32,
/* unique_entries */
finalPhaseMetric.getResponseCollective().getUniqueEntries(),
/* per_entry_counts */
finalPhaseMetric.getResponseCollective().getUniqueEntryCounts(),
/* unique_response_classtypes */
finalPhaseMetric.getResponseCollective().getUniqueResponseStrings(),
/* per_classtype_counts */
finalPhaseMetric.getResponseCollective().getUniqueResponseCounts(),
/* framework_exception_unique_classtypes */
DEFAULT_STRING
);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@@ -223,12 +224,18 @@ public class MetricUtilities {
metric.getQueryFinishTimeNanoseconds());
candidateStatusList[index] = metric.getProviderQueryStatus();
candidateHasExceptionList[index] = metric.isHasException();
candidateTotalEntryCountList[index] = metric.getNumEntriesTotal();
candidateCredentialEntryCountList[index] = metric.getCredentialEntryCount();
candidateCredentialTypeCountList[index] = metric.getCredentialEntryTypeCount();
candidateActionEntryCountList[index] = metric.getActionEntryCount();
candidateAuthEntryCountList[index] = metric.getAuthenticationEntryCount();
candidateRemoteEntryCountList[index] = metric.getRemoteEntryCount();
candidateTotalEntryCountList[index] = metric.getResponseCollective()
.getNumEntriesTotal();
candidateCredentialEntryCountList[index] = metric.getResponseCollective()
.getCountForEntry(EntryEnum.CREDENTIAL_ENTRY);
candidateCredentialTypeCountList[index] = metric.getResponseCollective()
.getUniqueResponseStrings().length;
candidateActionEntryCountList[index] = metric.getResponseCollective()
.getCountForEntry(EntryEnum.ACTION_ENTRY);
candidateAuthEntryCountList[index] = metric.getResponseCollective()
.getCountForEntry(EntryEnum.AUTHENTICATION_ENTRY);
candidateRemoteEntryCountList[index] = metric.getResponseCollective()
.getCountForEntry(EntryEnum.REMOTE_ENTRY);
frameworkExceptionList[index] = metric.getFrameworkException();
index++;
}
@@ -262,7 +269,7 @@ public class MetricUtilities {
initialPhaseMetric.getUniqueRequestCounts()
);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@@ -298,7 +305,7 @@ public class MetricUtilities {
DEFAULT_INT_32,
/* chosen_provider_status */ DEFAULT_INT_32);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@@ -331,7 +338,7 @@ public class MetricUtilities {
initialPhaseMetric.isOriginSpecified()
);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
}

View File

@@ -16,14 +16,12 @@
package com.android.server.credentials.metrics;
import android.util.IntArray;
import android.util.Log;
import com.android.server.credentials.MetricUtilities;
import com.android.server.credentials.metrics.shared.ResponseCollective;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
/**
* The central candidate provider metric object that mimics our defined metric setup.
@@ -55,23 +53,12 @@ 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 number of total entries available, defaults to -1
private int mNumEntriesTotal = -1;
// The count of action entries from this provider, defaults to -1
private int mActionEntryCount = -1;
// The count of credential entries from this provider, defaults to -1
private int mCredentialEntryCount = -1;
// The *type-count* of the credential entries, defaults to -1
private int mCredentialEntryTypeCount = -1;
// The count of remote entries from this provider, defaults to -1
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 final IntArray mAvailableEntries = new IntArray();
// The *framework only* exception held by this provider, empty string by default
private String mFrameworkException = "";
// 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());
public CandidatePhaseMetric() {
}
@@ -182,88 +169,13 @@ public class CandidatePhaseMetric {
return mHasException;
}
/* -------------- Number of Entries ---------------- */
public void setNumEntriesTotal(int numEntriesTotal) {
mNumEntriesTotal = numEntriesTotal;
/* -------------- The Entries and Responses Gathered ---------------- */
public void setResponseCollective(ResponseCollective responseCollective) {
mResponseCollective = responseCollective;
}
public int getNumEntriesTotal() {
return mNumEntriesTotal;
}
/* -------------- Count of Action Entries ---------------- */
public void setActionEntryCount(int actionEntryCount) {
mActionEntryCount = actionEntryCount;
}
public int getActionEntryCount() {
return mActionEntryCount;
}
/* -------------- Count of Credential Entries ---------------- */
public void setCredentialEntryCount(int credentialEntryCount) {
mCredentialEntryCount = credentialEntryCount;
}
public int getCredentialEntryCount() {
return mCredentialEntryCount;
}
/* -------------- Count of Credential Entry Types ---------------- */
public void setCredentialEntryTypeCount(int credentialEntryTypeCount) {
mCredentialEntryTypeCount = credentialEntryTypeCount;
}
public int getCredentialEntryTypeCount() {
return mCredentialEntryTypeCount;
}
/* -------------- Count of Remote Entries ---------------- */
public void setRemoteEntryCount(int remoteEntryCount) {
mRemoteEntryCount = remoteEntryCount;
}
public int getRemoteEntryCount() {
return mRemoteEntryCount;
}
/* -------------- Count of Authentication Entries ---------------- */
public void setAuthenticationEntryCount(int authenticationEntryCount) {
mAuthenticationEntryCount = authenticationEntryCount;
}
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) {
mAvailableEntries.add(e.getMetricCode());
}
/**
* 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<Integer> getAvailableEntries() {
return Arrays.stream(mAvailableEntries.toArray()).boxed().collect(Collectors.toList());
public ResponseCollective getResponseCollective() {
return mResponseCollective;
}
/* ------ Framework Exception for this Candidate ------ */

View File

@@ -19,9 +19,9 @@ package com.android.server.credentials.metrics;
import android.util.Log;
import com.android.server.credentials.MetricUtilities;
import com.android.server.credentials.metrics.shared.ResponseCollective;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* The central chosen provider metric object that mimics our defined metric setup. This is used
@@ -66,21 +66,10 @@ public class ChosenProviderFinalPhaseMetric {
private int mChosenProviderStatus = -1;
// Indicates if an exception was thrown by this provider, false by default
private boolean mHasException = false;
// Indicates the number of total entries available, defaults to -1. Not presently emitted, but
// left as a utility
private int mNumEntriesTotal = -1;
// The count of action entries from this provider, defaults to -1
private int mActionEntryCount = -1;
// The count of credential entries from this provider, defaults to -1
private int mCredentialEntryCount = -1;
// The *type-count* of the credential entries, defaults to -1
private int mCredentialEntryTypeCount = -1;
// The count of remote entries from this provider, defaults to -1
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<Integer> mAvailableEntries = new ArrayList<>();
// 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());
public ChosenProviderFinalPhaseMetric() {
@@ -264,87 +253,6 @@ public class ChosenProviderFinalPhaseMetric {
return mUiReturned;
}
/* -------------- Number of Entries ---------------- */
public void setNumEntriesTotal(int numEntriesTotal) {
mNumEntriesTotal = numEntriesTotal;
}
public int getNumEntriesTotal() {
return mNumEntriesTotal;
}
/* -------------- Count of Action Entries ---------------- */
public void setActionEntryCount(int actionEntryCount) {
mActionEntryCount = actionEntryCount;
}
public int getActionEntryCount() {
return mActionEntryCount;
}
/* -------------- Count of Credential Entries ---------------- */
public void setCredentialEntryCount(int credentialEntryCount) {
mCredentialEntryCount = credentialEntryCount;
}
public int getCredentialEntryCount() {
return mCredentialEntryCount;
}
/* -------------- Count of Credential Entry Types ---------------- */
public void setCredentialEntryTypeCount(int credentialEntryTypeCount) {
mCredentialEntryTypeCount = credentialEntryTypeCount;
}
public int getCredentialEntryTypeCount() {
return mCredentialEntryTypeCount;
}
/* -------------- Count of Remote Entries ---------------- */
public void setRemoteEntryCount(int remoteEntryCount) {
mRemoteEntryCount = remoteEntryCount;
}
public int getRemoteEntryCount() {
return mRemoteEntryCount;
}
/* -------------- Count of Authentication Entries ---------------- */
public void setAuthenticationEntryCount(int authenticationEntryCount) {
mAuthenticationEntryCount = authenticationEntryCount;
}
public int getAuthenticationEntryCount() {
return mAuthenticationEntryCount;
}
/* -------------- The Entries Gathered ---------------- */
/**
* Sets the collected list of entries from the candidate phase to be retrievable in the
* chosen phase in a semantically correct way.
*/
public void setAvailableEntries(List<Integer> entries) {
mAvailableEntries = new ArrayList<>(entries); // no alias copy
}
/**
* Returns a list of the entries captured by this metric collector associated
* with a particular chosen provider.
*
* @return the full collection of entries encountered by the chosen provider during the
* candidate phase.
*/
public List<Integer> getAvailableEntries() {
return new ArrayList<>(mAvailableEntries); // no alias copy
}
/* -------------- Has Exception ---------------- */
public void setHasException(boolean hasException) {
@@ -354,4 +262,14 @@ public class ChosenProviderFinalPhaseMetric {
public boolean isHasException() {
return mHasException;
}
/* -------------- The Entries and Responses Gathered ---------------- */
public void setResponseCollective(ResponseCollective responseCollective) {
mResponseCollective = responseCollective;
}
public ResponseCollective getResponseCollective() {
return mResponseCollective;
}
}

View File

@@ -48,7 +48,7 @@ public class InitialPhaseMetric {
// Indicates if the origin was specified when making this API request
private boolean mOriginSpecified = false;
// Stores the deduped request information, particularly {"req":5}.
// Stores the deduped request information, particularly {"req":5}
private Map<String, Integer> mRequestCounts = new LinkedHashMap<>();
@@ -138,7 +138,7 @@ public class InitialPhaseMetric {
}
/**
* Reruns the unique, deduped, request classtypes for logging.
* Returns the unique, deduped, request classtypes for logging.
* @return a string array for deduped classtypes
*/
public String[] getUniqueRequestStrings() {
@@ -151,7 +151,7 @@ public class InitialPhaseMetric {
}
/**
* Reruns the unique, deduped, request classtype counts for logging.
* Returns the unique, deduped, request classtype counts for logging.
* @return a string array for deduped classtype counts
*/
public int[] getUniqueRequestCounts() {

View File

@@ -16,15 +16,19 @@
package com.android.server.credentials.metrics;
import static com.android.server.credentials.MetricUtilities.DELTA_CUT;
import static com.android.server.credentials.MetricUtilities.generateMetricKey;
import android.annotation.NonNull;
import android.service.credentials.BeginCreateCredentialResponse;
import android.service.credentials.BeginGetCredentialResponse;
import android.service.credentials.CredentialEntry;
import android.util.Log;
import android.util.Slog;
import com.android.server.credentials.MetricUtilities;
import com.android.server.credentials.metrics.shared.ResponseCollective;
import java.util.stream.Collectors;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Provides contextual metric collection for objects generated from
@@ -68,7 +72,7 @@ public class ProviderSessionMetric {
try {
mCandidatePhasePerProviderMetric.setFrameworkException(exceptionType);
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@@ -97,7 +101,7 @@ public class ProviderSessionMetric {
.getMetricCode());
}
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@@ -118,7 +122,7 @@ public class ProviderSessionMetric {
initMetric.getCredentialServiceStartedTimeNanoseconds());
mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
@@ -138,59 +142,53 @@ public class ProviderSessionMetric {
beginCreateCredentialResponseCollectionCandidateEntryMetrics(
(BeginCreateCredentialResponse) response);
} else {
Log.i(TAG, "Your response type is unsupported for metric logging");
Slog.i(TAG, "Your response type is unsupported for metric logging");
}
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);
Slog.w(TAG, "Unexpected error during metric logging: " + e);
}
}
private void beginCreateCredentialResponseCollectionCandidateEntryMetrics(
BeginCreateCredentialResponse response) {
Map<EntryEnum, Integer> entryCounts = new LinkedHashMap<>();
var createEntries = response.getCreateEntries();
int numRemoteEntry = MetricUtilities.ZERO;
if (response.getRemoteCreateEntry() != null) {
numRemoteEntry = MetricUtilities.UNIT;
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.REMOTE_ENTRY);
}
int numCreateEntries =
createEntries == null ? MetricUtilities.ZERO : createEntries.size();
if (numCreateEntries > MetricUtilities.ZERO) {
createEntries.forEach(c ->
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.CREDENTIAL_ENTRY));
}
mCandidatePhasePerProviderMetric.setNumEntriesTotal(numCreateEntries + numRemoteEntry);
mCandidatePhasePerProviderMetric.setRemoteEntryCount(numRemoteEntry);
mCandidatePhasePerProviderMetric.setCredentialEntryCount(numCreateEntries);
mCandidatePhasePerProviderMetric.setCredentialEntryTypeCount(MetricUtilities.UNIT);
int numRemoteEntry = response.getRemoteCreateEntry() != null ? MetricUtilities.ZERO :
MetricUtilities.UNIT;
int numCreateEntries = createEntries.size();
entryCounts.put(EntryEnum.REMOTE_ENTRY, numRemoteEntry);
entryCounts.put(EntryEnum.CREDENTIAL_ENTRY, numCreateEntries);
Map<String, Integer> responseCounts = new LinkedHashMap<>();
responseCounts.put(MetricUtilities.DEFAULT_STRING, numCreateEntries);
// We don't store create response because it's directly related to the request
// We do still store the count, however
ResponseCollective responseCollective = new ResponseCollective(responseCounts, entryCounts);
mCandidatePhasePerProviderMetric.setResponseCollective(responseCollective);
}
private void beginGetCredentialResponseCollectionCandidateEntryMetrics(
BeginGetCredentialResponse response) {
Map<EntryEnum, Integer> entryCounts = new LinkedHashMap<>();
Map<String, Integer> responseCounts = new LinkedHashMap<>();
int numCredEntries = response.getCredentialEntries().size();
int numActionEntries = response.getActions().size();
int numAuthEntries = response.getAuthenticationActions().size();
int numRemoteEntry = MetricUtilities.ZERO;
if (response.getRemoteCredentialEntry() != null) {
numRemoteEntry = MetricUtilities.UNIT;
mCandidatePhasePerProviderMetric.addEntry(EntryEnum.REMOTE_ENTRY);
}
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 + numRemoteEntry);
mCandidatePhasePerProviderMetric.setCredentialEntryCount(numCredEntries);
int numTypes = (response.getCredentialEntries().stream()
.map(CredentialEntry::getType).collect(
Collectors.toSet())).size(); // Dedupe type strings
mCandidatePhasePerProviderMetric.setCredentialEntryTypeCount(numTypes);
mCandidatePhasePerProviderMetric.setActionEntryCount(numActionEntries);
mCandidatePhasePerProviderMetric.setAuthenticationEntryCount(numAuthEntries);
mCandidatePhasePerProviderMetric.setRemoteEntryCount(numRemoteEntry);
int numRemoteEntry = response.getRemoteCredentialEntry() != null ? MetricUtilities.ZERO :
MetricUtilities.UNIT;
entryCounts.put(EntryEnum.REMOTE_ENTRY, numRemoteEntry);
entryCounts.put(EntryEnum.CREDENTIAL_ENTRY, numCredEntries);
entryCounts.put(EntryEnum.ACTION_ENTRY, numActionEntries);
entryCounts.put(EntryEnum.AUTHENTICATION_ENTRY, numAuthEntries);
response.getCredentialEntries().forEach(entry -> {
String entryKey = generateMetricKey(entry.getType(), DELTA_CUT);
responseCounts.put(entryKey, responseCounts.getOrDefault(entryKey, 0) + 1);
});
ResponseCollective responseCollective = new ResponseCollective(responseCounts, entryCounts);
mCandidatePhasePerProviderMetric.setResponseCollective(responseCollective);
}
}

View File

@@ -272,21 +272,8 @@ public class RequestSessionMetric {
candidatePhaseMetric.getStartQueryTimeNanoseconds());
mChosenProviderFinalPhaseMetric.setQueryEndTimeNanoseconds(candidatePhaseMetric
.getQueryFinishTimeNanoseconds());
mChosenProviderFinalPhaseMetric.setNumEntriesTotal(candidatePhaseMetric
.getNumEntriesTotal());
mChosenProviderFinalPhaseMetric.setCredentialEntryCount(candidatePhaseMetric
.getCredentialEntryCount());
mChosenProviderFinalPhaseMetric.setCredentialEntryTypeCount(
candidatePhaseMetric.getCredentialEntryTypeCount());
mChosenProviderFinalPhaseMetric.setActionEntryCount(candidatePhaseMetric
.getActionEntryCount());
mChosenProviderFinalPhaseMetric.setRemoteEntryCount(candidatePhaseMetric
.getRemoteEntryCount());
mChosenProviderFinalPhaseMetric.setAuthenticationEntryCount(
candidatePhaseMetric.getAuthenticationEntryCount());
mChosenProviderFinalPhaseMetric.setAvailableEntries(candidatePhaseMetric
.getAvailableEntries());
mChosenProviderFinalPhaseMetric.setResponseCollective(
candidatePhaseMetric.getResponseCollective());
mChosenProviderFinalPhaseMetric.setFinalFinishTimeNanoseconds(System.nanoTime());
} catch (Exception e) {
Log.w(TAG, "Unexpected error during metric logging: " + e);

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.credentials.metrics.shared;
import android.annotation.NonNull;
import android.util.Slog;
import com.android.server.credentials.metrics.EntryEnum;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Some data is directly shared between the
* {@link com.android.server.credentials.metrics.CandidatePhaseMetric} and the
* {@link com.android.server.credentials.metrics.ChosenProviderFinalPhaseMetric}. This
* aims to create an abstraction that holds that information, to avoid duplication.
*
* This class should be immutable and threadsafe once generated.
*/
public class ResponseCollective {
/*
Abstract Function (responseCounts, entryCounts) -> A 'ResponseCollective' containing information
about a chosen or candidate providers available responses, be they entries or credentials.
RepInvariant: mResponseCounts and mEntryCounts are always initialized
Threadsafe and Immutability: Once generated, the maps remain unchangeable. The object is
threadsafe and immutable, and safe from external changes. This is threadsafe because it is
immutable after creation and only allows reads, not writes.
*/
private static final String TAG = "ResponseCollective";
// Stores the deduped credential response information, eg {"response":5} for this provider
private final Map<String, Integer> mResponseCounts;
// Stores the deduped entry information, eg {ENTRY_ENUM:5} for this provider
private final Map<EntryEnum, Integer> mEntryCounts;
public ResponseCollective(@NonNull Map<String, Integer> responseCounts,
@NonNull Map<EntryEnum, Integer> entryCounts) {
mResponseCounts = responseCounts == null ? new LinkedHashMap<>() :
new LinkedHashMap<>(responseCounts);
mEntryCounts = entryCounts == null ? new LinkedHashMap<>() :
new LinkedHashMap<>(entryCounts);
}
/**
* Returns the unique, deduped, response classtypes for logging associated with this provider.
*
* @return a string array for deduped classtypes
*/
public String[] getUniqueResponseStrings() {
if (mResponseCounts.isEmpty()) {
Slog.w(TAG, "There are no unique string response types collected");
}
String[] result = new String[mResponseCounts.keySet().size()];
mResponseCounts.keySet().toArray(result);
return result;
}
/**
* Returns the unique, deduped, response classtype counts for logging associated with this
* provider.
* @return a string array for deduped classtype counts
*/
public int[] getUniqueResponseCounts() {
if (mResponseCounts.isEmpty()) {
Slog.w(TAG, "There are no unique string response type counts collected");
}
return mResponseCounts.values().stream().mapToInt(Integer::intValue).toArray();
}
/**
* Returns the unique, deduped, entry types for logging associated with this provider.
* @return an int array for deduped entries
*/
public int[] getUniqueEntries() {
if (mEntryCounts.isEmpty()) {
Slog.w(TAG, "There are no unique entry response types collected");
}
return mEntryCounts.keySet().stream().mapToInt(Enum::ordinal).toArray();
}
/**
* Returns the unique, deduped, entry classtype counts for logging associated with this
* provider.
* @return a string array for deduped classtype counts
*/
public int[] getUniqueEntryCounts() {
if (mEntryCounts.isEmpty()) {
Slog.w(TAG, "There are no unique entry response type counts collected");
}
return mEntryCounts.values().stream().mapToInt(Integer::intValue).toArray();
}
/**
* Given a specific {@link EntryEnum}, this provides us with the count of that entry within
* this particular provider.
* @param e the entry enum with which we want to know the count of
* @return a count of this particular entry enum stored by this provider
*/
public int getCountForEntry(EntryEnum e) {
return mEntryCounts.get(e);
}
/**
* Indicates the total number of existing entries for this provider.
* @return a count of the total number of entries for this provider
*/
public int getNumEntriesTotal() {
return mEntryCounts.values().stream().mapToInt(Integer::intValue).sum();
}
}