From d5b8749006555da6018855d208b86df522c5ff5d Mon Sep 17 00:00:00 2001 From: Arpan Kaphle Date: Thu, 27 Apr 2023 04:17:43 +0000 Subject: [PATCH 1/3] Candidate Aggregate Metrics Setup + sessId Focus This sets up the design for how candidate aggregate metrics will be collected, and runs through the whole flow up to emits. Currently, many values are default values, and will be filled in as the design is extended out. It does handle the split session id logic, however, between the two tracks. Also, after deliberation, we now use the hashCode of a random UUID to get closer to ~ (1/2^(32)) collision rate - their hashcode is pretty random, utilizing an int conversion from a bitwise xor operation of the most and least significant bits from the already high entropy uuid. This will provide more security than the binder implementation, especially under time and device id buckets, against collisions. Bug: 271135048 Test: Build and Won't Submit without E2E Test Change-Id: I8e7455dd6eaf8adb15035f6a9262f34a0c20531f --- .../credentials/CredentialManagerService.java | 2 + .../server/credentials/MetricUtilities.java | 70 +++++++++++++++++++ .../server/credentials/RequestSession.java | 2 +- .../metrics/CandidateAggregateMetric.java | 50 +++++++++++++ .../metrics/CandidateBrowsingPhaseMetric.java | 12 ---- .../metrics/ProviderSessionMetric.java | 2 +- .../metrics/RequestSessionMetric.java | 34 +++++++-- 7 files changed, 153 insertions(+), 19 deletions(-) create mode 100644 services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java index 8728c3c647159..f4b745e3db4e4 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java @@ -697,6 +697,8 @@ public final class CredentialManagerService initMetric.setCredentialServiceBeginQueryTimeNanoseconds(System.nanoTime()); MetricUtilities.logApiCalledInitialPhase(initMetric, session.mRequestSessionMetric.returnIncrementSequence()); + session.mRequestSessionMetric.getCandidateAggregateMetric().setSessionId( + initMetric.getSessionId()); } catch (Exception e) { Slog.i(TAG, "Unexpected error during metric logging: ", e); } diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java index 40a4bc2468898..e1854fa3ed1dd 100644 --- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java +++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java @@ -24,12 +24,14 @@ import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; import com.android.server.credentials.metrics.ApiName; import com.android.server.credentials.metrics.ApiStatus; +import com.android.server.credentials.metrics.CandidateAggregateMetric; 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.security.SecureRandom; import java.util.List; import java.util.Map; @@ -78,6 +80,15 @@ public class MetricUtilities { return sessUid; } + /** + * Used to help generate random sequences for local sessions, in the time-scale of credential + * manager flows. + * @return a high entropy int useful to use in reasonable time-frame sessions. + */ + public static int getHighlyUniqueInteger() { + return new SecureRandom().nextInt(); + } + /** * Given any two timestamps in nanoseconds, this gets the difference and converts to * milliseconds. Assumes the difference is not larger than the maximum int size. @@ -336,4 +347,63 @@ public class MetricUtilities { Slog.w(TAG, "Unexpected error during initial metric emit: " + e); } } + + /** + * A logging utility focused on track 1, where the calling app is known. This captures all + * aggregate information for the candidate phase. + * + * @param candidateAggregateMetric the aggregate candidate metric information collected + * @param sequenceNum the sequence number for this api call session emit + */ + public static void logApiCalledAggregateCandidate( + CandidateAggregateMetric candidateAggregateMetric, + int sequenceNum) { + try { + if (!LOG_FLAG) { + FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_TOTAL_REPORTED, + /*session_id*/ candidateAggregateMetric.getSessionId(), + /*sequence_num*/ sequenceNum, + /*query_returned*/ true, + /*num_query_providers*/ DEFAULT_INT_32, + /*min_query_start_timestamp_microseconds*/ + DEFAULT_INT_32, + /*max_query_end_timestamp_microseconds*/ + DEFAULT_INT_32, + /*query_response_unique_classtypes*/ + DEFAULT_REPEATED_STR, + /*query_per_classtype_counts*/ + DEFAULT_REPEATED_INT_32, + /*query_unique_entries*/ + DEFAULT_REPEATED_INT_32, + /*query_per_entry_counts*/ + DEFAULT_REPEATED_INT_32, + /*query_total_candidate_failure*/ + DEFAULT_INT_32, + /*query_framework_exception_unique_classtypes*/ + DEFAULT_REPEATED_STR, + /*query_per_exception_classtype_counts*/ + DEFAULT_REPEATED_INT_32, + /*auth_response_unique_classtypes*/ + DEFAULT_REPEATED_STR, + /*auth_per_classtype_counts*/ + DEFAULT_REPEATED_INT_32, + /*auth_unique_entries*/ + DEFAULT_REPEATED_INT_32, + /*auth_per_entry_counts*/ + DEFAULT_REPEATED_INT_32, + /*auth_total_candidate_failure*/ + DEFAULT_INT_32, + /*auth_framework_exception_unique_classtypes*/ + DEFAULT_REPEATED_STR, + /*auth_per_exception_classtype_counts*/ + DEFAULT_REPEATED_INT_32, + /*num_auth_clicks*/ + DEFAULT_INT_32, + /*auth_returned*/ false + ); + } + } catch (Exception e) { + Slog.w(TAG, "Unexpected error during metric logging: " + e); + } + } } diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java index 7caa921eacda5..350a0bef80847 100644 --- a/services/credentials/java/com/android/server/credentials/RequestSession.java +++ b/services/credentials/java/com/android/server/credentials/RequestSession.java @@ -132,7 +132,7 @@ abstract class RequestSession implements CredentialManagerUi.Credential mUserId, this, mEnabledProviders); mHybridService = context.getResources().getString( R.string.config_defaultCredentialManagerHybridService); - mRequestSessionMetric.collectInitialPhaseMetricInfo(timestampStarted, mRequestId, + mRequestSessionMetric.collectInitialPhaseMetricInfo(timestampStarted, mCallingUid, ApiName.getMetricCodeFromRequestInfo(mRequestType)); setCancellationListener(); } diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java new file mode 100644 index 0000000000000..25c2d9b6c112a --- /dev/null +++ b/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java @@ -0,0 +1,50 @@ +/* + * 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; + +import com.android.server.credentials.ProviderSession; + +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. + */ +public class CandidateAggregateMetric { + + private static final String TAG = "CandidateProviderMetric"; + // The session id of this provider, default set to -1 + private int mSessionId = -1; + + public void setSessionId(int sessionId) { + mSessionId = sessionId; + } + + public int getSessionId() { + return mSessionId; + } + + /** + * This will take all the candidate data captured and aggregate that information. + * TODO(b/271135048) : Add on authentication entry outputs from track 2 here as well once + * generated + * @param providers a map that associates with all provider sessions + */ + public void collectAverages(Map providers) { + // TODO(b/271135048) : Complete this method + } +} diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java index 07af6549411ea..6b74252dec193 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java @@ -27,23 +27,11 @@ package com.android.server.credentials.metrics; * though collection will begin in the candidate phase when the user begins browsing options. */ public class CandidateBrowsingPhaseMetric { - // The session id associated with the API Call this candidate provider is a part of, default -1 - private int mSessionId = -1; // The EntryEnum that was pressed, defaults to -1 private int mEntryEnum = EntryEnum.UNKNOWN.getMetricCode(); // The provider associated with the press, defaults to -1 private int mProviderUid = -1; - /* -- The session ID -- */ - - public void setSessionId(int sessionId) { - mSessionId = sessionId; - } - - public int getSessionId() { - return mSessionId; - } - /* -- The Entry of this tap -- */ public void setEntryEnum(int entryEnum) { diff --git a/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java index e77636ca3845e..b0016e764a395 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java @@ -119,7 +119,7 @@ public class ProviderSessionMetric { */ public void collectCandidateMetricSetupViaInitialMetric(InitialPhaseMetric initMetric) { try { - mCandidatePhasePerProviderMetric.setSessionId(initMetric.getSessionId()); + mCandidatePhasePerProviderMetric.setSessionId(MetricUtilities.getHighlyUniqueInteger()); mCandidatePhasePerProviderMetric.setServiceBeganTimeNanoseconds( initMetric.getCredentialServiceStartedTimeNanoseconds()); mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime()); diff --git a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java index 4874378a8c218..0c43f6fab6927 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java @@ -22,11 +22,12 @@ import static com.android.server.credentials.MetricUtilities.generateMetricKey; import static com.android.server.credentials.MetricUtilities.logApiCalledCandidatePhase; import static com.android.server.credentials.MetricUtilities.logApiCalledFinalPhase; +import android.annotation.NonNull; import android.credentials.GetCredentialRequest; import android.credentials.ui.UserSelectionDialogResult; -import android.os.IBinder; import android.util.Slog; +import com.android.server.credentials.MetricUtilities; import com.android.server.credentials.ProviderSession; import java.util.ArrayList; @@ -53,6 +54,10 @@ public class RequestSessionMetric { mChosenProviderFinalPhaseMetric = new ChosenProviderFinalPhaseMetric(); // TODO(b/271135048) - Replace this with a new atom per each browsing emit (V4) protected List mCandidateBrowsingPhaseMetric = new ArrayList<>(); + // Specific aggregate candidate provider metric for the provider this session handles + @NonNull + protected final CandidateAggregateMetric mCandidateAggregateMetric = + new CandidateAggregateMetric(); public RequestSessionMetric() { } @@ -75,19 +80,25 @@ public class RequestSessionMetric { return mInitialPhaseMetric; } + /** + * @return the aggregate candidate phase metrics associated with the request session + */ + public CandidateAggregateMetric getCandidateAggregateMetric() { + return mCandidateAggregateMetric; + } + /** * Upon starting the service, this fills the initial phase metric properly. * * @param timestampStarted the timestamp the service begins at - * @param mRequestId the IBinder used to retrieve a unique id * @param mCallingUid the calling process's uid * @param metricCode typically pulled from {@link ApiName} */ - public void collectInitialPhaseMetricInfo(long timestampStarted, IBinder mRequestId, + public void collectInitialPhaseMetricInfo(long timestampStarted, int mCallingUid, int metricCode) { try { mInitialPhaseMetric.setCredentialServiceStartedTimeNanoseconds(timestampStarted); - mInitialPhaseMetric.setSessionId(mRequestId.hashCode()); + mInitialPhaseMetric.setSessionId(MetricUtilities.getHighlyUniqueInteger()); mInitialPhaseMetric.setCallerUid(mCallingUid); mInitialPhaseMetric.setApiName(metricCode); } catch (Exception e) { @@ -206,7 +217,6 @@ public class RequestSessionMetric { CandidatePhaseMetric selectedProviderPhaseMetric) { try { CandidateBrowsingPhaseMetric browsingPhaseMetric = new CandidateBrowsingPhaseMetric(); - browsingPhaseMetric.setSessionId(mInitialPhaseMetric.getSessionId()); browsingPhaseMetric.setEntryEnum( EntryEnum.getMetricCodeFromString(selection.getEntryKey())); browsingPhaseMetric.setProviderUid(selectedProviderPhaseMetric.getCandidateUid()); @@ -331,6 +341,20 @@ public class RequestSessionMetric { } } + /** + * Handles aggregate candidate phase metric emits in the RequestSession context, after the + * candidate phase completes. + * + * @param providers a map with known providers and their held metric objects + */ + public void logCandidateAggregateMetrics(Map providers) { + try { + mCandidateAggregateMetric.collectAverages(providers); + } catch (Exception e) { + Slog.i(TAG, "Unexpected error during aggregate candidate logging " + e); + } + } + /** * Handles the final logging for RequestSession context for the final phase. * From f3b471ad79c42a02628687c1aca0f3819e96a7ef Mon Sep 17 00:00:00 2001 From: Arpan Kaphle Date: Thu, 27 Apr 2023 20:14:27 +0000 Subject: [PATCH 2/3] Adds to Aggregate Candidate Metric query and count Also, designs setup for authentication entry collection, and creates a new abstraction object for said collection. Given that authentication entries can occur in loops, this starts to think about how we might aggregate authentication entries. On top of this, this re-designs the session id in the collection system so that it is immutable once created. Bug: 271135048 Test: Build + Won't submit w/o E2E test Change-Id: Ib32036430f5cf0249a651a2867758de08f19e63b --- .../credentials/CredentialManagerService.java | 2 - .../server/credentials/MetricUtilities.java | 11 +++-- .../credentials/ProviderCreateSession.java | 4 +- .../credentials/ProviderGetSession.java | 5 ++- .../server/credentials/ProviderSession.java | 14 ++++++- .../server/credentials/RequestSession.java | 10 ++++- .../metrics/BrowsedAuthenticationMetric.java | 35 ++++++++++++++++ .../metrics/CandidateAggregateMetric.java | 33 +++++++++++++-- .../metrics/CandidatePhaseMetric.java | 13 +++--- .../ChosenProviderFinalPhaseMetric.java | 20 +++++---- .../metrics/InitialPhaseMetric.java | 9 ++-- .../metrics/ProviderSessionMetric.java | 42 +++++++++++++++---- .../metrics/RequestSessionMetric.java | 27 ++++++++---- 13 files changed, 164 insertions(+), 61 deletions(-) create mode 100644 services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java index f4b745e3db4e4..8728c3c647159 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java @@ -697,8 +697,6 @@ public final class CredentialManagerService initMetric.setCredentialServiceBeginQueryTimeNanoseconds(System.nanoTime()); MetricUtilities.logApiCalledInitialPhase(initMetric, session.mRequestSessionMetric.returnIncrementSequence()); - session.mRequestSessionMetric.getCandidateAggregateMetric().setSessionId( - initMetric.getSessionId()); } catch (Exception e) { Slog.i(TAG, "Unexpected error during metric logging: ", e); } diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java index e1854fa3ed1dd..704a22837002d 100644 --- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java +++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java @@ -141,7 +141,7 @@ public class MetricUtilities { index++; } FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_FINAL_PHASE_REPORTED, - /* session_id */ finalPhaseMetric.getSessionId(), + /* session_id */ finalPhaseMetric.getSessionIdTrackTwo(), /* sequence_num */ emitSequenceId, /* ui_returned_final_start */ finalPhaseMetric.isUiReturned(), /* chosen_provider_uid */ finalPhaseMetric.getChosenUid(), @@ -181,8 +181,7 @@ public class MetricUtilities { finalPhaseMetric.getResponseCollective().getUniqueResponseCounts(), /* framework_exception_unique_classtype */ finalPhaseMetric.getFrameworkException(), - /* primary_indicated */ - false + /* primary_indicated */ false ); } catch (Exception e) { Slog.w(TAG, "Unexpected error during final provider uid emit: " + e); @@ -226,7 +225,7 @@ public class MetricUtilities { CandidatePhaseMetric metric = session.mProviderSessionMetric .getCandidatePhasePerProviderMetric(); if (sessionId == -1) { - sessionId = metric.getSessionId(); + sessionId = metric.getSessionIdTrackTwo(); } if (!queryReturned) { queryReturned = metric.isQueryReturned(); @@ -363,8 +362,8 @@ public class MetricUtilities { FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_TOTAL_REPORTED, /*session_id*/ candidateAggregateMetric.getSessionId(), /*sequence_num*/ sequenceNum, - /*query_returned*/ true, - /*num_query_providers*/ DEFAULT_INT_32, + /*query_returned*/ candidateAggregateMetric.isQueryReturned(), + /*num_providers*/ candidateAggregateMetric.getNumProviders(), /*min_query_start_timestamp_microseconds*/ DEFAULT_INT_32, /*max_query_end_timestamp_microseconds*/ diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java index 16beaa4eb13e9..19a098eb84283 100644 --- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java +++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java @@ -193,11 +193,11 @@ public final class ProviderCreateSession extends ProviderSession< mProviderResponseDataHandler.addResponseContent(response.getCreateEntries(), response.getRemoteCreateEntry()); if (mProviderResponseDataHandler.isEmptyResponse(response)) { - mProviderSessionMetric.collectCandidateEntryMetrics(response); + mProviderSessionMetric.collectCandidateEntryMetrics(response, /*isAuthEntry*/false); updateStatusAndInvokeCallback(Status.EMPTY_RESPONSE, /*source=*/ CredentialsSource.REMOTE_PROVIDER); } else { - mProviderSessionMetric.collectCandidateEntryMetrics(response); + mProviderSessionMetric.collectCandidateEntryMetrics(response, /*isAuthEntry*/false); updateStatusAndInvokeCallback(Status.SAVE_ENTRIES_RECEIVED, /*source=*/ CredentialsSource.REMOTE_PROVIDER); } diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java index 1e80703378e0c..28bc9de25cd80 100644 --- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java +++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java @@ -432,6 +432,7 @@ public final class ProviderGetSession extends ProviderSession @NonNull protected Boolean mProviderResponseSet = false; @NonNull - protected final ProviderSessionMetric mProviderSessionMetric = new ProviderSessionMetric(); + protected final ProviderSessionMetric mProviderSessionMetric; @NonNull private int mProviderSessionUid; @@ -113,6 +113,13 @@ public abstract class ProviderSession return status == Status.COMPLETE || status == Status.EMPTY_RESPONSE; } + /** + * Gives access to the objects metric collectors. + */ + public ProviderSessionMetric getProviderSessionMetric() { + return this.mProviderSessionMetric; + } + /** * Interface to be implemented by any class that wishes to get a callback when a particular * provider session's status changes. Typically, implemented by the {@link RequestSession} @@ -147,6 +154,8 @@ public abstract class ProviderSession mComponentName = componentName; mRemoteCredentialService = remoteCredentialService; mProviderSessionUid = MetricUtilities.getPackageUid(mContext, mComponentName); + mProviderSessionMetric = new ProviderSessionMetric( + ((RequestSession) mCallbacks).mRequestSessionMetric.getSessionIdTrackTwo()); } /** Provider status at various states of the provider session. */ @@ -206,7 +215,8 @@ public abstract class ProviderSession CredentialsSource source) { setStatus(status); mProviderSessionMetric.collectCandidateMetricUpdate(isTerminatingStatus(status), - isCompletionStatus(status), mProviderSessionUid); + isCompletionStatus(status), mProviderSessionUid, + source == CredentialsSource.AUTH_ENTRY); mCallbacks.onProviderStatusChanged(status, mComponentName, source); } /** Common method that transfers metrics from the init phase to candidates */ diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java index 350a0bef80847..fb7aef0b7bd1c 100644 --- a/services/credentials/java/com/android/server/credentials/RequestSession.java +++ b/services/credentials/java/com/android/server/credentials/RequestSession.java @@ -75,6 +75,8 @@ abstract class RequestSession implements CredentialManagerUi.Credential protected final Handler mHandler; @UserIdInt protected final int mUserId; + + protected final int mUniqueSessionInteger; private final int mCallingUid; @NonNull protected final CallingAppInfo mClientAppInfo; @@ -82,7 +84,7 @@ abstract class RequestSession implements CredentialManagerUi.Credential protected final CancellationSignal mCancellationSignal; protected final Map mProviders = new ConcurrentHashMap<>(); - protected final RequestSessionMetric mRequestSessionMetric = new RequestSessionMetric(); + protected final RequestSessionMetric mRequestSessionMetric; protected final String mHybridService; protected final Object mLock; @@ -132,8 +134,12 @@ abstract class RequestSession implements CredentialManagerUi.Credential mUserId, this, mEnabledProviders); mHybridService = context.getResources().getString( R.string.config_defaultCredentialManagerHybridService); + mUniqueSessionInteger = MetricUtilities.getHighlyUniqueInteger(); + mRequestSessionMetric = new RequestSessionMetric(mUniqueSessionInteger, + MetricUtilities.getHighlyUniqueInteger()); mRequestSessionMetric.collectInitialPhaseMetricInfo(timestampStarted, - mCallingUid, ApiName.getMetricCodeFromRequestInfo(mRequestType)); + mCallingUid, ApiName.getMetricCodeFromRequestInfo(mRequestType), + mUniqueSessionInteger); setCancellationListener(); } diff --git a/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java b/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java new file mode 100644 index 0000000000000..20e33738b6e42 --- /dev/null +++ b/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java @@ -0,0 +1,35 @@ +/* + * 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; + +/** + * Encapsulates an authentication entry click atom, as a part of track 2. + * Contains information about what was collected from the authentication entry output. + */ +public class BrowsedAuthenticationMetric { + private final int mSessionIdTrackTwo; + // TODO(b/271135048) - Match the atom and provide a clean per provider session metric + // encapsulation. + + public BrowsedAuthenticationMetric(int sessionIdTrackTwo) { + mSessionIdTrackTwo = sessionIdTrackTwo; + } + + public int getSessionIdTrackTwo() { + return mSessionIdTrackTwo; + } +} diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java index 25c2d9b6c112a..acf608447c64a 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java @@ -28,10 +28,16 @@ public class CandidateAggregateMetric { private static final String TAG = "CandidateProviderMetric"; // The session id of this provider, default set to -1 - private int mSessionId = -1; + private final int mSessionId; + // Indicates if this provider returned from the query phase, default false + private boolean mQueryReturned = false; + // Indicates the total number of providers this aggregate captures information for, default 0 + private int mNumProviders = 0; + // Indicates the total number of authentication entries that were tapped in aggregate, default 0 + private int mNumAuthEntriesTapped = 0; - public void setSessionId(int sessionId) { - mSessionId = sessionId; + public CandidateAggregateMetric(int sessionIdTrackOne) { + mSessionId = sessionIdTrackOne; } public int getSessionId() { @@ -42,9 +48,28 @@ public class CandidateAggregateMetric { * This will take all the candidate data captured and aggregate that information. * TODO(b/271135048) : Add on authentication entry outputs from track 2 here as well once * generated - * @param providers a map that associates with all provider sessions + * @param providers the providers associated with the candidate flow */ public void collectAverages(Map providers) { // TODO(b/271135048) : Complete this method + mNumProviders = providers.size(); + var providerSessions = providers.values(); + for (var session : providerSessions) { + var metric = session.getProviderSessionMetric(); + mQueryReturned = mQueryReturned || metric + .mCandidatePhasePerProviderMetric.isQueryReturned(); + } + } + + public int getNumProviders() { + return mNumProviders; + } + + public boolean isQueryReturned() { + return mQueryReturned; + } + + public int getNumAuthEntriesTapped() { + return mNumAuthEntriesTapped; } } diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java index cb2e71f8ba9b1..9d7268f180e6e 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java @@ -33,7 +33,7 @@ public class CandidatePhaseMetric { private static final String TAG = "CandidateProviderMetric"; // The session id of this provider, default set to -1 - private int mSessionId = -1; + private final int mSessionIdTrackTwo; // Indicates if this provider returned from the query phase, default false private boolean mQueryReturned = false; @@ -60,7 +60,8 @@ public class CandidatePhaseMetric { // by default, contains empty info private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of()); - public CandidatePhaseMetric() { + public CandidatePhaseMetric(int sessionIdTrackTwo) { + mSessionIdTrackTwo = sessionIdTrackTwo; } /* ---------- Latencies ---------- */ @@ -142,12 +143,8 @@ public class CandidatePhaseMetric { /* -------------- Session Id ---------------- */ - public void setSessionId(int sessionId) { - mSessionId = sessionId; - } - - public int getSessionId() { - return mSessionId; + public int getSessionIdTrackTwo() { + return mSessionIdTrackTwo; } /* -------------- Query Returned Status ---------------- */ diff --git a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java index 6af686587b88e..7e9c8baa564cc 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java @@ -32,8 +32,12 @@ import java.util.Map; */ public class ChosenProviderFinalPhaseMetric { private static final String TAG = "ChosenFinalPhaseMetric"; - // The session id associated with this API call, used to unite split emits - private int mSessionId = -1; + // The session id associated with this API call, used to unite split emits, for the flow + // where we know the calling app + private final int mSessionIdTrackOne; + // The session id associated with this API call, used to unite split emits, for the flow + // where we know the provider apps + private final int mSessionIdTrackTwo; // Reveals if the UI was returned, false by default private boolean mUiReturned = false; private int mChosenUid = -1; @@ -74,7 +78,9 @@ public class ChosenProviderFinalPhaseMetric { private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of()); - public ChosenProviderFinalPhaseMetric() { + public ChosenProviderFinalPhaseMetric(int sessionIdTrackOne, int sessionIdTrackTwo) { + mSessionIdTrackOne = sessionIdTrackOne; + mSessionIdTrackTwo = sessionIdTrackTwo; } /* ------------------- UID ------------------- */ @@ -237,12 +243,8 @@ public class ChosenProviderFinalPhaseMetric { /* ----------- Session ID -------------- */ - public void setSessionId(int sessionId) { - mSessionId = sessionId; - } - - public int getSessionId() { - return mSessionId; + public int getSessionIdTrackTwo() { + return mSessionIdTrackTwo; } /* ----------- UI Returned Successfully -------------- */ diff --git a/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java index 060e56ce965b3..eb88d37639436 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java @@ -33,7 +33,7 @@ public class InitialPhaseMetric { // The caller uid of the calling application, default to -1 private int mCallerUid = -1; // The session id to unite multiple atom emits, default to -1 - private int mSessionId = -1; + private final int mSessionId; // Raw timestamps in nanoseconds, *the only* one logged as such (i.e. 64 bits) since it is a // reference point. @@ -50,7 +50,8 @@ public class InitialPhaseMetric { private Map mRequestCounts = new LinkedHashMap<>(); - public InitialPhaseMetric() { + public InitialPhaseMetric(int sessionIdTrackOne) { + mSessionId = sessionIdTrackOne; } /* ---------- Latencies ---------- */ @@ -105,10 +106,6 @@ public class InitialPhaseMetric { /* ------ SessionId ------ */ - public void setSessionId(int sessionId) { - mSessionId = sessionId; - } - public int getSessionId() { return mSessionId; } diff --git a/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java index b0016e764a395..47db8f59ff355 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/ProviderSessionMetric.java @@ -44,10 +44,17 @@ public class ProviderSessionMetric { // Specific candidate provider metric for the provider this session handles @NonNull - protected final CandidatePhaseMetric mCandidatePhasePerProviderMetric = - new CandidatePhaseMetric(); + protected final CandidatePhaseMetric mCandidatePhasePerProviderMetric; - public ProviderSessionMetric() {} + // IFF there was an authentication entry clicked, this stores all required information for + // that event. This is for the 'get' flow. + @NonNull + protected final BrowsedAuthenticationMetric mBrowsedAuthenticationMetric; + + public ProviderSessionMetric(int sessionIdTrackTwo) { + mCandidatePhasePerProviderMetric = new CandidatePhaseMetric(sessionIdTrackTwo); + mBrowsedAuthenticationMetric = new BrowsedAuthenticationMetric(sessionIdTrackTwo); + } /** * Retrieve the candidate provider phase metric and the data it contains. @@ -56,6 +63,7 @@ public class ProviderSessionMetric { return mCandidatePhasePerProviderMetric; } + /** * This collects for ProviderSessions, with respect to the candidate providers, whether * an exception occurred in the candidate call. @@ -78,6 +86,13 @@ 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. + } + /** * Used to collect metrics at the update stage when a candidate provider gives back an update. * @@ -86,8 +101,12 @@ public class ProviderSessionMetric { * @param providerSessionUid the uid of the provider */ public void collectCandidateMetricUpdate(boolean isFailureStatus, - boolean isCompletionStatus, int providerSessionUid) { + boolean isCompletionStatus, int providerSessionUid, boolean isAuthEntry) { try { + if (isAuthEntry) { + collectAuthEntryUpdate(isFailureStatus, isCompletionStatus, providerSessionUid); + return; + } mCandidatePhasePerProviderMetric.setCandidateUid(providerSessionUid); mCandidatePhasePerProviderMetric .setQueryFinishTimeNanoseconds(System.nanoTime()); @@ -119,7 +138,6 @@ public class ProviderSessionMetric { */ public void collectCandidateMetricSetupViaInitialMetric(InitialPhaseMetric initMetric) { try { - mCandidatePhasePerProviderMetric.setSessionId(MetricUtilities.getHighlyUniqueInteger()); mCandidatePhasePerProviderMetric.setServiceBeganTimeNanoseconds( initMetric.getCredentialServiceStartedTimeNanoseconds()); mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime()); @@ -133,13 +151,14 @@ public class ProviderSessionMetric { * purposes. * * @param response contains entries and data from the candidate provider responses + * @param isAuthEntry indicates if this is an auth entry collection or not * @param the response type associated with the API flow in progress */ - public void collectCandidateEntryMetrics(R response) { + public void collectCandidateEntryMetrics(R response, boolean isAuthEntry) { try { if (response instanceof BeginGetCredentialResponse) { beginGetCredentialResponseCollectionCandidateEntryMetrics( - (BeginGetCredentialResponse) response); + (BeginGetCredentialResponse) response, isAuthEntry); } else if (response instanceof BeginCreateCredentialResponse) { beginCreateCredentialResponseCollectionCandidateEntryMetrics( (BeginCreateCredentialResponse) response); @@ -198,7 +217,7 @@ public class ProviderSessionMetric { } private void beginGetCredentialResponseCollectionCandidateEntryMetrics( - BeginGetCredentialResponse response) { + BeginGetCredentialResponse response, boolean isAuthEntry) { Map entryCounts = new LinkedHashMap<>(); Map responseCounts = new LinkedHashMap<>(); int numCredEntries = response.getCredentialEntries().size(); @@ -217,6 +236,11 @@ public class ProviderSessionMetric { }); ResponseCollective responseCollective = new ResponseCollective(responseCounts, entryCounts); - mCandidatePhasePerProviderMetric.setResponseCollective(responseCollective); + + if (!isAuthEntry) { + mCandidatePhasePerProviderMetric.setResponseCollective(responseCollective); + } else { + // TODO(b/immediately) - Add the auth entry get logic + } } } diff --git a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java index 0c43f6fab6927..a399b1935accf 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java @@ -27,7 +27,6 @@ import android.credentials.GetCredentialRequest; import android.credentials.ui.UserSelectionDialogResult; import android.util.Slog; -import com.android.server.credentials.MetricUtilities; import com.android.server.credentials.ProviderSession; import java.util.ArrayList; @@ -49,17 +48,24 @@ public class RequestSessionMetric { // As emits occur in sequential order, increment this counter and utilize protected int mSequenceCounter = 0; - protected final InitialPhaseMetric mInitialPhaseMetric = new InitialPhaseMetric(); + protected final InitialPhaseMetric mInitialPhaseMetric; protected final ChosenProviderFinalPhaseMetric - mChosenProviderFinalPhaseMetric = new ChosenProviderFinalPhaseMetric(); + mChosenProviderFinalPhaseMetric; // TODO(b/271135048) - Replace this with a new atom per each browsing emit (V4) protected List mCandidateBrowsingPhaseMetric = new ArrayList<>(); // Specific aggregate candidate provider metric for the provider this session handles @NonNull - protected final CandidateAggregateMetric mCandidateAggregateMetric = - new CandidateAggregateMetric(); + protected final CandidateAggregateMetric mCandidateAggregateMetric; + // Since track two is shared, this allows provider sessions to capture a metric-specific + // session token for the flow where the provider is known + private final int mSessionIdTrackTwo; - public RequestSessionMetric() { + public RequestSessionMetric(int sessionIdTrackOne, int sessionIdTrackTwo) { + mSessionIdTrackTwo = sessionIdTrackTwo; + mInitialPhaseMetric = new InitialPhaseMetric(sessionIdTrackOne); + mCandidateAggregateMetric = new CandidateAggregateMetric(sessionIdTrackOne); + mChosenProviderFinalPhaseMetric = new ChosenProviderFinalPhaseMetric( + sessionIdTrackOne, sessionIdTrackTwo); } /** @@ -93,12 +99,13 @@ public class RequestSessionMetric { * @param timestampStarted the timestamp the service begins at * @param mCallingUid the calling process's uid * @param metricCode typically pulled from {@link ApiName} + * @param callingAppFlowUniqueInt the unique integer used as the session id for the calling app + * known flow */ public void collectInitialPhaseMetricInfo(long timestampStarted, - int mCallingUid, int metricCode) { + int mCallingUid, int metricCode, int callingAppFlowUniqueInt) { try { mInitialPhaseMetric.setCredentialServiceStartedTimeNanoseconds(timestampStarted); - mInitialPhaseMetric.setSessionId(MetricUtilities.getHighlyUniqueInteger()); mInitialPhaseMetric.setCallerUid(mCallingUid); mInitialPhaseMetric.setApiName(metricCode); } catch (Exception e) { @@ -284,7 +291,6 @@ public class RequestSessionMetric { */ public void collectChosenMetricViaCandidateTransfer(CandidatePhaseMetric candidatePhaseMetric) { try { - mChosenProviderFinalPhaseMetric.setSessionId(candidatePhaseMetric.getSessionId()); mChosenProviderFinalPhaseMetric.setChosenUid(candidatePhaseMetric.getCandidateUid()); mChosenProviderFinalPhaseMetric.setQueryPhaseLatencyMicroseconds( @@ -370,4 +376,7 @@ public class RequestSessionMetric { } } + public int getSessionIdTrackTwo() { + return mSessionIdTrackTwo; + } } From 59f28d4865c6ddd6f5d8cb68a3e7873924218587 Mon Sep 17 00:00:00 2001 From: Arpan Kaphle Date: Mon, 1 May 2023 01:25:10 +0000 Subject: [PATCH 3/3] Sets up Final Phase Emit for Calling App Track When we know the calling app, this sets up the final phase emit, where we do not know the providers. The session ID is properly transferred and different. We call this the 'track one' emit for the final phase. Bug: 271135048 Test: Build and won't submit without E2E test. Change-Id: If8cf0831f49eec7171c549fab1db471825fe6282 --- .../credentials/ClearRequestSession.java | 11 ++- .../credentials/CreateRequestSession.java | 10 ++- .../server/credentials/GetRequestSession.java | 10 ++- .../server/credentials/MetricUtilities.java | 74 ++++++++++++++++++- .../server/credentials/RequestSession.java | 3 +- .../metrics/BrowsedAuthenticationMetric.java | 11 +-- .../metrics/CandidateAggregateMetric.java | 10 +-- .../metrics/CandidatePhaseMetric.java | 10 +-- .../ChosenProviderFinalPhaseMetric.java | 20 +++-- .../metrics/InitialPhaseMetric.java | 10 +-- .../metrics/RequestSessionMetric.java | 6 +- 11 files changed, 132 insertions(+), 43 deletions(-) diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java index e9efe7eb62472..e3d4c224f1fda 100644 --- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java @@ -30,6 +30,8 @@ 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; @@ -93,9 +95,12 @@ public final class ClearRequestSession extends RequestSession browsingPhaseMetrics, int apiStatus, + int emitSequenceId) { + try { + if (!LOG_FLAG) { + return; + } + int browsedSize = browsingPhaseMetrics.size(); + int[] browsedClickedEntries = new int[browsedSize]; + int[] browsedProviderUid = new int[browsedSize]; + int index = 0; + for (CandidateBrowsingPhaseMetric metric : browsingPhaseMetrics) { + browsedClickedEntries[index] = metric.getEntryEnum(); + browsedProviderUid[index] = metric.getProviderUid(); + index++; + } + FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_FINALNOUID_REPORTED, + /* session_id */ finalPhaseMetric.getSessionIdCaller(), + /* sequence_num */ emitSequenceId, + /* ui_returned_final_start */ finalPhaseMetric.isUiReturned(), + /* chosen_provider_query_start_timestamp_microseconds */ + finalPhaseMetric.getTimestampFromReferenceStartMicroseconds(finalPhaseMetric + .getQueryStartTimeNanoseconds()), + /* chosen_provider_query_end_timestamp_microseconds */ + finalPhaseMetric.getTimestampFromReferenceStartMicroseconds(finalPhaseMetric + .getQueryEndTimeNanoseconds()), + /* chosen_provider_ui_invoked_timestamp_microseconds */ + finalPhaseMetric.getTimestampFromReferenceStartMicroseconds(finalPhaseMetric + .getUiCallStartTimeNanoseconds()), + /* chosen_provider_ui_finished_timestamp_microseconds */ + finalPhaseMetric.getTimestampFromReferenceStartMicroseconds(finalPhaseMetric + .getUiCallEndTimeNanoseconds()), + /* chosen_provider_finished_timestamp_microseconds */ + finalPhaseMetric.getTimestampFromReferenceStartMicroseconds(finalPhaseMetric + .getFinalFinishTimeNanoseconds()), + /* chosen_provider_status */ finalPhaseMetric.getChosenProviderStatus(), + /* chosen_provider_has_exception */ finalPhaseMetric.isHasException(), + /* 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_classtype */ + finalPhaseMetric.getFrameworkException(), + /* clicked_entries */ browsedClickedEntries, + /* provider_of_clicked_entry */ browsedProviderUid, + /* api_status */ apiStatus, + /* primary_indicated */ false + ); + } catch (Exception e) { + Slog.w(TAG, "Unexpected error during metric logging: " + e); + } + } + } diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java index fb7aef0b7bd1c..a41b5713ee145 100644 --- a/services/credentials/java/com/android/server/credentials/RequestSession.java +++ b/services/credentials/java/com/android/server/credentials/RequestSession.java @@ -138,8 +138,7 @@ abstract class RequestSession implements CredentialManagerUi.Credential mRequestSessionMetric = new RequestSessionMetric(mUniqueSessionInteger, MetricUtilities.getHighlyUniqueInteger()); mRequestSessionMetric.collectInitialPhaseMetricInfo(timestampStarted, - mCallingUid, ApiName.getMetricCodeFromRequestInfo(mRequestType), - mUniqueSessionInteger); + mCallingUid, ApiName.getMetricCodeFromRequestInfo(mRequestType)); setCancellationListener(); } diff --git a/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java b/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java index 20e33738b6e42..51e86d51acdfd 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/BrowsedAuthenticationMetric.java @@ -21,15 +21,16 @@ package com.android.server.credentials.metrics; * Contains information about what was collected from the authentication entry output. */ public class BrowsedAuthenticationMetric { - private final int mSessionIdTrackTwo; + // The session id of this provider known flow related metric + private final int mSessionIdProvider; // TODO(b/271135048) - Match the atom and provide a clean per provider session metric // encapsulation. - public BrowsedAuthenticationMetric(int sessionIdTrackTwo) { - mSessionIdTrackTwo = sessionIdTrackTwo; + public BrowsedAuthenticationMetric(int sessionIdProvider) { + mSessionIdProvider = sessionIdProvider; } - public int getSessionIdTrackTwo() { - return mSessionIdTrackTwo; + public int getSessionIdProvider() { + return mSessionIdProvider; } } diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java index acf608447c64a..08e75837a2748 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/CandidateAggregateMetric.java @@ -27,8 +27,8 @@ import java.util.Map; public class CandidateAggregateMetric { private static final String TAG = "CandidateProviderMetric"; - // The session id of this provider, default set to -1 - private final int mSessionId; + // The session id of this provider metric + private final int mSessionIdProvider; // Indicates if this provider returned from the query phase, default false private boolean mQueryReturned = false; // Indicates the total number of providers this aggregate captures information for, default 0 @@ -37,11 +37,11 @@ public class CandidateAggregateMetric { private int mNumAuthEntriesTapped = 0; public CandidateAggregateMetric(int sessionIdTrackOne) { - mSessionId = sessionIdTrackOne; + mSessionIdProvider = sessionIdTrackOne; } - public int getSessionId() { - return mSessionId; + public int getSessionIdProvider() { + return mSessionIdProvider; } /** diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java index 9d7268f180e6e..d9bf4a134adb9 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java @@ -32,8 +32,8 @@ import java.util.Map; public class CandidatePhaseMetric { private static final String TAG = "CandidateProviderMetric"; - // The session id of this provider, default set to -1 - private final int mSessionIdTrackTwo; + // The session id of this provider metric + private final int mSessionIdProvider; // Indicates if this provider returned from the query phase, default false private boolean mQueryReturned = false; @@ -61,7 +61,7 @@ public class CandidatePhaseMetric { private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of()); public CandidatePhaseMetric(int sessionIdTrackTwo) { - mSessionIdTrackTwo = sessionIdTrackTwo; + mSessionIdProvider = sessionIdTrackTwo; } /* ---------- Latencies ---------- */ @@ -143,8 +143,8 @@ public class CandidatePhaseMetric { /* -------------- Session Id ---------------- */ - public int getSessionIdTrackTwo() { - return mSessionIdTrackTwo; + public int getSessionIdProvider() { + return mSessionIdProvider; } /* -------------- Query Returned Status ---------------- */ diff --git a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java index 7e9c8baa564cc..e8af86012aaf9 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java @@ -34,10 +34,10 @@ public class ChosenProviderFinalPhaseMetric { private static final String TAG = "ChosenFinalPhaseMetric"; // The session id associated with this API call, used to unite split emits, for the flow // where we know the calling app - private final int mSessionIdTrackOne; + private final int mSessionIdCaller; // The session id associated with this API call, used to unite split emits, for the flow // where we know the provider apps - private final int mSessionIdTrackTwo; + private final int mSessionIdProvider; // Reveals if the UI was returned, false by default private boolean mUiReturned = false; private int mChosenUid = -1; @@ -78,9 +78,9 @@ public class ChosenProviderFinalPhaseMetric { private ResponseCollective mResponseCollective = new ResponseCollective(Map.of(), Map.of()); - public ChosenProviderFinalPhaseMetric(int sessionIdTrackOne, int sessionIdTrackTwo) { - mSessionIdTrackOne = sessionIdTrackOne; - mSessionIdTrackTwo = sessionIdTrackTwo; + public ChosenProviderFinalPhaseMetric(int sessionIdCaller, int sessionIdProvider) { + mSessionIdCaller = sessionIdCaller; + mSessionIdProvider = sessionIdProvider; } /* ------------------- UID ------------------- */ @@ -243,8 +243,8 @@ public class ChosenProviderFinalPhaseMetric { /* ----------- Session ID -------------- */ - public int getSessionIdTrackTwo() { - return mSessionIdTrackTwo; + public int getSessionIdProvider() { + return mSessionIdProvider; } /* ----------- UI Returned Successfully -------------- */ @@ -286,4 +286,10 @@ public class ChosenProviderFinalPhaseMetric { public String getFrameworkException() { return mFrameworkException; } + + /* -------------- Session ID for Track One (Known Calling App) ---------------- */ + + public int getSessionIdCaller() { + return mSessionIdCaller; + } } diff --git a/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java index eb88d37639436..8e965e3e5ba5d 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java @@ -32,8 +32,8 @@ public class InitialPhaseMetric { private int mApiName = ApiName.UNKNOWN.getMetricCode(); // The caller uid of the calling application, default to -1 private int mCallerUid = -1; - // The session id to unite multiple atom emits, default to -1 - private final int mSessionId; + // The session id to unite multiple atom emits + private final int mSessionIdCaller; // Raw timestamps in nanoseconds, *the only* one logged as such (i.e. 64 bits) since it is a // reference point. @@ -51,7 +51,7 @@ public class InitialPhaseMetric { public InitialPhaseMetric(int sessionIdTrackOne) { - mSessionId = sessionIdTrackOne; + mSessionIdCaller = sessionIdTrackOne; } /* ---------- Latencies ---------- */ @@ -106,8 +106,8 @@ public class InitialPhaseMetric { /* ------ SessionId ------ */ - public int getSessionId() { - return mSessionId; + public int getSessionIdCaller() { + return mSessionIdCaller; } /* ------ Count Request Class Types ------ */ diff --git a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java index a399b1935accf..03ffe23f98866 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java @@ -21,6 +21,7 @@ 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; +import static com.android.server.credentials.MetricUtilities.logApiCalledNoUidFinal; import android.annotation.NonNull; import android.credentials.GetCredentialRequest; @@ -103,7 +104,7 @@ public class RequestSessionMetric { * known flow */ public void collectInitialPhaseMetricInfo(long timestampStarted, - int mCallingUid, int metricCode, int callingAppFlowUniqueInt) { + int mCallingUid, int metricCode) { try { mInitialPhaseMetric.setCredentialServiceStartedTimeNanoseconds(timestampStarted); mInitialPhaseMetric.setCallerUid(mCallingUid); @@ -371,6 +372,9 @@ public class RequestSessionMetric { logApiCalledFinalPhase(mChosenProviderFinalPhaseMetric, mCandidateBrowsingPhaseMetric, apiStatus, ++mSequenceCounter); + logApiCalledNoUidFinal(mChosenProviderFinalPhaseMetric, mCandidateBrowsingPhaseMetric, + apiStatus, + ++mSequenceCounter); } catch (Exception e) { Slog.i(TAG, "Unexpected error during final metric emit: " + e); }