Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5b87490 authored by Arpan Kaphle's avatar Arpan Kaphle
Browse files

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
parent c8c01cc5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
            }
+70 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ abstract class RequestSession<T, U, V> 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();
    }
+50 −0
Original line number Diff line number Diff line
/*
 * 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<String, ProviderSession> providers) {
        // TODO(b/271135048) : Complete this method
    }
}
+0 −12
Original line number Diff line number Diff line
@@ -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) {
Loading