/*
 * 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.
 */
syntax = "proto2";
package android.os.statsd.credentials;
option java_package = "com.android.os.credentials";
option java_multiple_files = true;
import "frameworks/proto_logging/stats/atoms.proto";
import "frameworks/proto_logging/stats/atom_field_options.proto";

extend Atom {
    optional CredentialManagerApiCalled credential_manager_api_called = 585 [(module) = "framework", deprecated = true];
    optional CredentialManagerInitialPhaseReported credential_manager_init_phase_reported = 651 [(module) = "framework"];
    optional CredentialManagerCandidatePhaseReported credential_manager_candidate_phase_reported = 652 [(module) = "framework"];
    optional CredentialManagerFinalPhaseReported credential_manager_final_phase_reported = 653 [(module) = "framework"];
    optional CredentialManagerTotalCandidateReported credential_manager_total_reported = 667 [(module) = "framework"];
    optional CredentialManagerFinalNoUidReported credential_manager_finalnouid_reported = 668 [(module) = "framework"];
    optional CredentialManagerGetProviderReported credential_manager_get_reported = 669 [(module) = "framework"];
    optional CredentialManagerBrowsedAuthenticationClicked credential_manager_auth_click_reported = 670 [(module) = "framework"];
    optional CredentialManagerApiV2Called credential_manager_apiv2_called = 671 [(module) = "framework"];
}

/**
 * ProviderStatus needed throughout the logging. Reveals
 * the status of candidate and chosen providers.
 */
enum ProviderStatus {
    PROVIDER_UNKNOWN = 0;
    // Indicates a successful query phase
    PROVIDER_QUERY_SUCCESS = 1;
    // Indicates a successful final phase
    PROVIDER_FINAL_SUCCESS = 2;
    // Indicates a query failure
    PROVIDER_QUERY_FAILURE = 3;
    // Indicates general failure during our final phase
    PROVIDER_FINAL_FAILURE = 4;
}
/**
 * Used to represent the various entries shown
 * to the user, used throughout the logging.
 */
enum EntryEnum {
    UNKNOWN = 0;
    ACTION_ENTRY = 1;
    CREDENTIAL_ENTRY = 2;
    REMOTE_ENTRY = 3;
    AUTHENTICATION_ENTRY = 4;
}
/**
 * Used to represent the Api Names
 * that are captured in the flow.
 */
enum ApiName {
    API_NAME_UNKNOWN = 0;
    API_NAME_GET_CREDENTIAL = 1;
    API_NAME_CREATE_CREDENTIAL = 2;
    API_NAME_CLEAR_CREDENTIAL = 3;
    API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE = 4;
    API_NAME_SET_ENABLED_PROVIDERS = 5;
    API_NAME_GET_CREDENTIAL_PROVIDER_SERVICES = 6;
    API_NAME_REGISTER_CREDENTIAL_DESCRIPTION = 7;
    API_NAME_UNREGISTER_CREDENTIAL_DESCRIPTION = 8;
    API_NAME_GET_CREDENTIAL_VIA_REGISTRY = 9;
}
/**
 * Used to represent the Api Status
 * at the conclusion of the flow.
 */
enum ApiStatus {
    API_STATUS_UNKNOWN = 0;
    API_STATUS_SUCCESS = 1;
    API_STATUS_FAILURE = 2;
    API_STATUS_USER_CANCELED = 3;
    API_STATUS_CLIENT_CANCELED = 4;
    API_STATUS_BINDER_DIED = 5;
}

// The atoms below are a part of 'track 1', and have the same session id

/**
 * Logs when a CredentialManager api is called before the query phase.
 * Logged from:
 *   frameworks/base/services/credentials/java/com/android/server/credentials/...
 */
message CredentialManagerInitialPhaseReported {
    // The api name
    optional ApiName api_name = 1;
    // The calling app uid
    optional int32 caller_uid = 2 [(is_uid) = true];
    // A unique number to identify split emits
    optional int32 session_id = 3;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 4;
    // Reference nanoseconds for the start of the service call
    optional int64 initial_timestamp_reference_nanoseconds = 5;
    // A count of the number of request class types
    optional int32 count_credential_request_classtypes = 6 [deprecated = true];
    // The unique deduped classtypes
    repeated string request_unique_classtypes = 7;
    // The count per each classtype element in 'request_unique_classtypes'
    repeated int32 per_classtype_counts = 8;
    // Indicates if an origin was passed in
    optional bool origin_specified = 9;
    // The autofill session_id
    optional int32 autofill_session_id = 10;
    // The autofill session's request id
    optional int32 autofill_request_id = 11;
    // Indicates if this API call used the prepare flow
    optional bool api_used_prepare_flow = 12;
}

/**
 * This contains information across unknown providers for averages and
 * total counts, including the candidate get/create flows, and the
 * authentication flows. It should be noted that changes here may
 * need symmetric changes to the CredentialManagerBrowsedAuthenticationClicked
 * atom, especially with regards to the aggregate fields associated with
 * that entry.
 */
message CredentialManagerTotalCandidateReported {
    // A unique number to identify split emits
    optional int32 session_id = 1;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 2;
    // Query Start attempt is guaranteed by this emit
    optional bool query_returned = 3;
    // The number of providers visited
    optional int32 num_query_providers = 4;
    // Min of query start times - the time of the first provider queried
    optional int32 min_query_start_timestamp_microseconds = 5;
    // Max of query end times - the time of the last provider response
    optional int32 max_query_end_timestamp_microseconds = 6;
    // All deduped class types for cred responses across *all* providers
    // and get/create responses
    repeated string query_response_unique_classtypes = 7;
    // All deduped class types counts for cred responses across *all* providers
    // and get/create responses per element of 'response_unique_classtypes'
    repeated int32 query_per_classtype_counts = 8;
    // All deduped entries across providers, including get calls and auth entries
    repeated EntryEnum query_unique_entries = 9;
    // Counts per element entry in 'unique_entries' (avg can be computed via num_providers)
    repeated int32 query_per_entry_counts = 10;
    // Sum across all providers; 1 = fail, 0 = success. Average retrievable.
    optional int32 query_total_candidate_failure = 11;
    // The deduped exception class types
    repeated string query_framework_exception_unique_classtypes = 12;
    // The total count per element in 'framework_exception_unique_classtypes' - avg retrievable
    repeated int32 query_per_exception_classtype_counts = 13;
    // All deduped class types for cred responses across all auth entries
    repeated string auth_response_unique_classtypes = 14;
    // All deduped class types counts for cred responses across all auth entries
    repeated int32 auth_per_classtype_counts = 15;
    // All deduped entries across providers, for auth entries
    repeated EntryEnum auth_unique_entries = 16;
    // Counts per element entry in 'unique_entries' (avg can be computed via num_auth_clicks)
    repeated int32 auth_per_entry_counts = 17;
    // Sum across all auth entries; 1 = fail, 0 = success. Average retrievable.
    optional int32 auth_total_candidate_failure = 18;
    // The deduped exception class types for auth entries
    repeated string auth_framework_exception_unique_classtypes = 19;
    // The total count per element in 'framework_exception_unique_classtypes' - avg retrievable
    // for auth entries
    repeated int32 auth_per_exception_classtype_counts = 20;
    // The number of auth entries visited
    optional int32 num_auth_clicks = 21;
    // Indicates if at least one auth entry returned with data
    optional bool auth_returned = 22;
}

/**
 * Reasons for attempting to use config_oemCredentialManagerDialogComponent to fulfill the request.
 */
enum OemUiUsageStatus {
    OEM_UI_USAGE_STATUS_UNKNOWN = 0;
    // Success: the UI specified in config_oemCredentialManagerDialogComponent was used to
    // fulfill the request.
    OEM_UI_USAGE_STATUS_SUCCESS = 1;
    // The config value was not specified (e.g. left empty).
    OEM_UI_USAGE_STATUS_NOT_SPECIFIED = 2;
    // The config value component was specified but not found (e.g. component doesn't exist or
    // component isn't a system app).
    OEM_UI_USAGE_STATUS_SPECIFIED_BUT_NOT_FOUND = 3;
    // The config value component was found but not enabled.
    OEM_UI_USAGE_STATUS_SPECIFIED_BUT_NOT_ENABLED = 4;
}

/**
 * Logs when the UI Phase finishes and the credential is being returned. This is
 * used in track 1, and while track 2 is more or less identical, due to the disassociation
 * with session ids and provider uids, this is semantically a different atom.
 * Logged from:
 *   frameworks/base/services/credentials/java/com/android/server/credentials/...
 */
message CredentialManagerFinalNoUidReported {
    // A unique number to identify split emits
    optional int32 session_id = 1;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 2;
    // A checkpoint indicating the ui returned and final response began
    // Ui start is guaranteed given this emit
    optional bool final_ui_returned = 3;
    // Chosen Provider Section
    // The timestamp, normalized from call began as '0' when the query phase starts
    optional int32 final_query_start_timestamp_microseconds = 4;
    // The timestamp when the query phase ends
    optional int32 final_query_end_timestamp_microseconds = 5;
    // The timestamp when the ui phase is invoked
    optional int32 final_ui_invoked_timestamp_microseconds = 6;
    // The timestamp when the ui phase ends
    optional int32 final_ui_finished_timestamp_microseconds = 7;
    // The timestamp when the final phase ends (returned to client)
    optional int32 final_finished_timestamp_microseconds = 8;
    // The status of the chosen provider
    optional ProviderStatus final_status = 9;
    // Reveals if there was an exception in the final phase from the chosen provider
    optional bool provider_exception_occurred = 10;
    // Reveals the deduped entries available
    repeated EntryEnum unique_entries = 11;
    // The total count per each deduped entry element in 'final_unique_entries'
    repeated int32 per_entry_counts = 12;
    // The response class types for the chosen provider deduped
    repeated string response_unique_classtypes = 13;
    // The total count per unique classtype element in 'response_unique_classtypes'
    repeated int32 per_classtype_counts = 14;
    // The framework-side-only exception class type as a string if occurred
    // per provider
    optional string framework_exception_unique_classtype = 15;
    // Selection Phase (the user may tap on many of these)
    // The chain of clicked entries regardless of provider
    repeated EntryEnum clicked_entries = 16;
    // The provider associated with the clicked entry element in 'clicked_entries'
    repeated int32 per_entry_provider_uids = 17 [(is_uid) = true];
    // Final Information
    // The api result status
    optional ApiStatus api_status = 18;
    // Indicates if the chosen provider was a primary provider
    optional bool primary_indicated = 19;
    // The app uid of the package name section of the config_oemCredentialManagerDialogComponent,
    // the OEM specified system privileged UI for fulfilling this request.
    optional int32 oem_credential_manager_ui_uid = 20 [(is_uid) = true];
    // The app uid of the package name section of the
    // config_fallbackCredentialManagerDialogComponent, the fallback system UI for fulfilling
    // this request.
    optional int32 fallback_credential_manager_ui_uid = 21 [(is_uid) = true];
    // Status of attempting to use config_oemCredentialManagerDialogComponent to fulfill the
    // request.
    optional OemUiUsageStatus oem_ui_usage_status = 22;
    // Indicates the chosen classtype of the final tapped credential or create
    // entry
    optional string chosen_classtype = 23;
}

// The atoms below are a part of 'track 2', and have the same session id, separate
// from other tracks

/**
 * Logs when a CredentialManager API's query phase finishes.
 * Logged from:
 *   frameworks/base/services/credentials/java/com/android/server/credentials/...
 */
message CredentialManagerCandidatePhaseReported {
    // A unique number to identify split emits
    optional int32 session_id = 1;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 2;
    // A checkpoint indicating the query returned
    // Query Start attempt is guaranteed by this emit
    optional bool query_returned = 3;
    // Interaction with providers
    // Candidate Provider Section
    repeated int32 candidate_provider_uid = 4 [(is_uid) = true];
    // The timestamp, normalized from call began as '0' when the query phase starts
    repeated int32 candidate_provider_query_start_timestamp_microseconds = 5;
    // The timestamp when the query phase ends
    repeated int32 candidate_provider_query_end_timestamp_microseconds = 6;
    // The status of the candidate provider
    repeated ProviderStatus candidate_provider_status = 7;
    // A bit to indicate if the provider threw an exception
    repeated bool candidate_provider_has_exception = 8;
    // Indicates the number of available entries for this provider
    repeated int32 candidate_provider_num_entries = 9;
    // The number of action entries
    repeated int32 candidate_provider_action_entry_count = 10;
    // The number of credential entries
    repeated int32 candidate_provider_credential_entry_count = 11;
    // The number of *types* of credential entries
    repeated int32 candidate_provider_credential_entry_type_count = 12;
    // The number of remote entries
    repeated int32 candidate_provider_remote_entry_count = 13;
    // The number of authentication entries
    repeated int32 candidate_provider_authentication_entry_count = 14;
    // The framework-side-only exception class type as a string if occurred
    // per provider
    repeated string framework_exception_per_provider = 15;
    // Indicates if the initial request had an origin passed in
    optional bool origin_specified = 16;
    // The unique deduped classtypes of the request to this phase
    repeated string request_unique_classtypes = 17;
    // The count per each classtype element in 'request_unique_classtypes'
    repeated int32 per_classtype_counts = 18;
    // The api name for the metric collection flow where the calling app isn't known
    optional ApiName api_name = 19;
    // Indicates for all returned candidates if that candidate was primary
    repeated bool primary_candidates_indicated = 20;
    // Indicates if this API call used the prepare flow
    optional bool api_used_prepare_flow = 21;
}

/**
 * Since nesting is not recommended, this will reveal for *multiple candidate providers*
 * what *each* provider contained as far as the response class types are concerned. This is
 * needed for the Get flow, otherwise the information is lost, and we only have a count instead.
 * We are not going to collect the create flow as the response is mappable from the request.
 */
message CredentialManagerGetProviderReported {
    // A unique number to identify split emits
    optional int32 session_id = 1;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 2;
    optional int32 candidate_provider_uid = 3 [(is_uid) = true];
    // The list of unique response class type
    repeated string response_unique_classtypes = 4;
    // The count of total (credential) responses per element of 'response_unique_classtypes'
    repeated int32 per_classtype_counts = 5;
}

/**
 * During the UI Phase, there can be looped 'candidate' responses.
 * This is due to the Authentication Entry, which can allow the provider
 * to generate 'more' candidates. This atom captures these details.
 */
message CredentialManagerBrowsedAuthenticationClicked {
    // A unique number to identify split emits
    optional int32 session_id = 1;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 2;
    // Candidate Provider Section
    optional int32 candidate_provider_uid = 3 [(is_uid) = true];
    // The deduped set of response classtypes for this clicked auth entry
    repeated string response_unique_classtypes = 4;
    // The count per each deduped type in 'response_unique_classtypes'
    repeated int32 per_classtype_counts= 5;
    // Reveals the deduped entries associated with this provider
    repeated EntryEnum unique_entries = 6;
    // The count per deduped entry element in 'unique_entries'
    repeated int32 auth_per_entry_counts = 7;
    // The framework-side-only exception class type as a string if occurred
    // per provider
    optional string framework_exception_unique_classtype = 8;
    // Indciates if any exception occurred in this auth entry click
    optional bool exception_specified = 9;
    // Indicates the provider status after calling for auth entry credentials
    optional ProviderStatus candidate_provider_status = 10;
    // A checkpoint indicating the query returned
    // Query Start attempt is guaranteed by this emit
    optional bool query_returned = 11;
}

/**
 * Logs when the UI Phase finishes and the credential is being returned.
 * This version contains the uid, so it is the origin version, now in track 2.
 * Logged from:
 *   frameworks/base/services/credentials/java/com/android/server/credentials/...
 */
message CredentialManagerFinalPhaseReported {
    // A unique number to identify split emits
    optional int32 session_id = 1;
    // A sequence id to chronologically connect emits given races
    optional int32 sequence_num = 2;
    // A checkpoint indicating the ui returned and final response began
    // Ui start is guaranteed given this emit
    optional bool ui_returned_final_start = 3;
    // Chosen Provider Section
    // This is deprecated, and will not be logged - the server will correspond
    optional int32 chosen_provider_uid = 4 [(is_uid) = true];
    // The timestamp, normalized from call began as '0' when the query phase starts
    optional int32 chosen_provider_query_start_timestamp_microseconds = 5;
    // The timestamp when the query phase ends
    optional int32 chosen_provider_query_end_timestamp_microseconds = 6;
    // The timestamp when the ui phase is invoked
    optional int32 chosen_provider_ui_invoked_timestamp_microseconds = 7;
    // The timestamp when the ui phase ends
    optional int32 chosen_provider_ui_finished_timestamp_microseconds = 8;
    // The timestamp when the final phase ends (returned to client)
    optional int32 chosen_provider_finished_timestamp_microseconds = 9;
    // The status of the chosen provider
    optional ProviderStatus chosen_provider_status = 10;
    // Reveals if there was an exception in the chosen_provider
    optional bool chosen_provider_has_exception = 11;
    // Reveals all entries, deprecated for newly named 'unique_entries'
    repeated EntryEnum chosen_provider_available_entries = 12 [deprecated = true];
    // The number of action entries - deprecated with enum counts
    optional int32 chosen_provider_action_entry_count = 13 [deprecated = true];
    // The number of credential entries total - deprecated with string additions
    optional int32 chosen_provider_credential_entry_count = 14 [deprecated = true];
    // The number of *types* of credential entries - deprecated with string additions
    optional int32 chosen_provider_credential_entry_type_count = 15 [deprecated = true];
    // The number of remote entries - deprecated with enum counts
    optional int32 chosen_provider_remote_entry_count = 16 [deprecated = true];
    // The number of authentication entries - deprecated with enum counts
    optional int32 chosen_provider_authentication_entry_count = 17 [deprecated = true];
    // Selection Phase (the user may tap on many of these)
    // The chain of clicked entries regardless of provider
    repeated EntryEnum clicked_entries = 18;
    // The provider associated with the clicked entry above
    repeated int32 provider_of_clicked_entry = 19 [(is_uid) = true];
    // Final Information
    // The api result status
    optional ApiStatus api_status = 20;
    // Reveals the deduped entries associated with this provider
    repeated EntryEnum unique_entries = 21;
    // The count per unique entry element in 'unique_entries'
    repeated int32 per_entry_counts = 22;
    // The response class types for the chosen provider deduped
    repeated string unique_response_classtypes = 23;
    // The count per response classtype element in 'unique_response_classtypes'
    repeated int32 per_classtype_counts = 24;
    // The framework-side-only exception class type as a string if occurred
    // per provider
    optional string framework_exception_unique_classtype = 25;
    // Indicates if the chosen provider was a primary provider
    optional bool primary_indicated = 26;
    // Indicates the chosen classtype of the final tapped credential or create
    // entry
    optional string chosen_classtype = 27;
}

// The atoms below are a part of 'track 3', and have no session id

/**
 * Not all APIs are complex, and so this allows capturing simpler APIs.
 * It also allows a simpler query form, so existing complex APIs can also
 * utilize this as necessary so that aggregate info across *ALL* APIs can
 * neatly be queried under a single Atom. This may not be emitted in more
 * complex cases when the UI stays up, but the purpose is not to capture
 * intermediate data in those instances (the other splits do that).
 */
message CredentialManagerApiV2Called {
    // The api name
    optional ApiName api_name = 1;
    // The calling app uid
    optional int32 caller_uid = 2 [(is_uid) = true];
    // The api result status
    optional ApiStatus api_status = 3;
}

// The atoms below are older atoms that will begin the deprecation process

/**
 * Logs when a CredentialManager api is called.
 * Logged from:
 *   frameworks/base/services/credentials/java/com/android/server/credentials/...
 */
message CredentialManagerApiCalled {
    // The api name
    optional ApiName api_name = 1;
    // The calling app uid
    optional int32 caller_uid = 2 [(is_uid) = true];
    // The api result status
    optional ApiStatus api_status = 3;
    // Interaction with providers
    // Candidate Provider Section
    repeated int32 candidate_provider_uid = 4 [(is_uid) = true];
    // From invocation to when the query was returned, we record this time
    repeated int32 candidate_provider_round_trip_time_overall_microseconds = 5;
    repeated ProviderStatus candidate_provider_status = 6;
    // Chosen Provider Section
    optional int32 chosen_provider_uid = 7 [(is_uid) = true];
    // From invocation to when the final credential is returned
    optional int32 chosen_provider_round_trip_time_overall_microseconds = 8;
    // From the post query press to when the final credential is returned
    optional int32 chosen_provider_round_trip_time_choice_microseconds = 9;
    optional ProviderStatus chosen_provider_status = 10;
}
