/*
 * 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.healthfitness.api;

import "frameworks/proto_logging/stats/atoms.proto";
import "frameworks/proto_logging/stats/atom_field_options.proto";
import "frameworks/proto_logging/stats/enums/healthfitness/api/enums.proto";

option java_multiple_files = true;
option java_package = "com.android.os.healthfitness.api";

extend Atom {
  optional HealthConnectApiCalled health_connect_api_called = 616 [(module) = "healthfitness"];

  optional HealthConnectUsageStats health_connect_usage_stats = 617 [(module) = "healthfitness"];

  optional HealthConnectStorageStats health_connect_storage_stats = 618 [(module) = "healthfitness"];

  optional HealthConnectApiInvoked health_connect_api_invoked = 643 [(module) = "healthfitness", (restriction_category) = RESTRICTION_DIAGNOSTIC];

  optional ExerciseRouteApiCalled exercise_route_api_called = 654 [(module) = "healthfitness", (restriction_category) = RESTRICTION_DIAGNOSTIC];

  optional HealthConnectExportInvoked health_connect_export_invoked = 907 [(module) = "healthfitness"];

  optional HealthConnectImportInvoked health_connect_import_invoked = 918 [(module) = "healthfitness"];

  optional HealthConnectExportImportStatsReported health_connect_export_import_stats_reported = 919 [(module) = "healthfitness"];

  optional HealthConnectPermissionStats health_connect_permission_stats = 963 [(module) = "healthfitness"];

  optional HealthConnectPhrApiInvoked health_connect_phr_api_invoked = 980 [(module) = "healthfitness", (restriction_category) = RESTRICTION_DIAGNOSTIC];

  optional HealthConnectPhrUsageStats health_connect_phr_usage_stats = 981 [(module) = "healthfitness"];

  optional HealthConnectPhrStorageStats health_connect_phr_storage_stats = 984 [(module) = "healthfitness"];

  optional HealthConnectRestrictedEcosystemStats health_connect_restricted_ecosystem_stats = 985 [(module) = "healthfitness", (restriction_category) = RESTRICTION_DIAGNOSTIC];

  optional HealthConnectEcosystemStats health_connect_ecosystem_stats = 986 [(module) = "healthfitness"];

  optional HealthConnectDataBackupInvoked health_connect_data_backup_invoked = 1023 [(module) = "healthfitness"];

  optional HealthConnectMetadataBackupInvoked health_connect_metadata_backup_invoked = 1024 [(module) = "healthfitness"];

  optional HealthConnectDataRestoreInvoked health_connect_data_restore_invoked = 1025 [(module) = "healthfitness"];

  optional HealthConnectMetadataRestoreInvoked health_connect_metadata_restore_invoked = 1026 [(module) = "healthfitness"];

  optional HealthConnectRestoreEligibilityChecked health_connect_restore_eligibility_checked = 1027 [(module) = "healthfitness"];

  optional HealthConnectLatencyStats health_connect_latency_stats = 1140 [(module) = "healthfitness"];

  optional HealthConnectRecordingMethodStats health_connect_recording_method_stats = 1157 [(module) = "healthfitness", (restriction_category) = RESTRICTION_DIAGNOSTIC];

  optional HealthConnectDeviceInfoStats health_connect_device_info_stats = 1160 [(module) = "healthfitness", (restriction_category) = RESTRICTION_DIAGNOSTIC];

  optional HealthConnectDataGranularityStats health_connect_data_granularity_stats = 1165 [(module) = "healthfitness"];
  optional HealthConnectNativeTrackingStatsReported health_connect_native_tracking_stats_reported = 1167 [(module) = "healthfitness"];
}

// Track HealthDataService API operations.
message HealthConnectApiCalled {

  // API method invoked.
  optional android.healthfitness.api.ApiMethod api_method = 1;

  // Status whether the API call executed successfully or not.
  optional android.healthfitness.api.ApiStatus api_status = 2;

  // Only relevant when status == ERROR;
  optional int32 error_code = 3;

  // Total API call duration in milliseconds.
  optional int64 duration_millis = 4;

  // Number of records being inserted/updated etc. (If any)
  optional int32 number_of_records = 5;

  // Type of rate limiting being used (If any)
  optional android.healthfitness.api.RateLimit rate_limit = 6;

  // The API caller's foreground status
  optional android.healthfitness.api.ForegroundState caller_foreground_state = 7;

  // Package calling the API. We will remove any package with less than certain number of installs (500k for now) from aggregations.
  optional string package_name = 8;
}

// Track if users are connecting apps with Health Connect
message HealthConnectUsageStats {

  // Number of connected apps
  optional int32 connected_apps_count = 1;

  // Number of apps on device that can be connected to Health Connect.
  optional int32 available_apps_count = 2;

  // Set true is the user has one app reading or writing in past 30 days
  optional bool is_monthly_active_user = 3;

}

// Track if users are connecting personal health record apps with Health Connect
message HealthConnectPhrUsageStats {

  // Number of connected medical data sources
  optional int32 connected_medical_datasource_count = 1;

  // Number of stored medical resources.
  optional int32 medical_resource_count = 2;

  // Set true if the user has one read medical resources API call in past 30
  // days. PHR stands for Personal Health Record.
  optional bool is_monthly_active_phr_user = 3;

  // Number of apps that have been granted at least one medical data read
  // permission. PHR stands for Personal Health Record.
  optional int32 granted_phr_apps_count = 4;

}

/**
 *  Tracks the daily usage stats of the Health Connect export/import feature.
 *
 *  Logged from:
 *  packages/modules/HealthFitness/service/java/com/android/server/healthconnect/logging/UsageStatsLogger.java
 *
 *  Estimated Logging Rate:
 *  Avg: 1 per device per day
 *
 */
message HealthConnectExportImportStatsReported {

  // Configured export frequency of the user
  optional int32 export_frequency = 1;

}

// Monitor Health Connect database
message HealthConnectStorageStats {

  // Size of database
  optional int64 database_size = 1;

  // Total number of instant records in the database.
  optional int64 instant_data_count = 2;

  // Total number of interval records in the database.
  optional int64 interval_data_count = 3;

  // Total number of series records in the database.
  optional int64 series_data_count = 4;

  // Total number of changelog counts.
  optional int64 changelog_count = 5;
}

// Monitor PHR database in HC (PHR stands for Personal Health Record)
message HealthConnectPhrStorageStats {
  optional int64 phr_data_size = 1;
}

// Track when ExerciseRoute is being read/written.
message ExerciseRouteApiCalled {

  // Read/write.
  optional android.healthfitness.api.Operation operation = 1;

  // Package name of the client that invoked the API.
  optional string package_name = 2;

  // Number of records under operation
  optional int32 number_of_records = 3;

}

/**
 * Tracks when a data export is started or changes status.
 */
message HealthConnectExportInvoked {

  // Status of the export (started/success/failure)
  optional android.healthfitness.api.ExportStatus status = 1;

  // Time taken between the start of the export and its conclusion.
  optional int32 time_to_succeed_or_fail_millis = 2;

  // Size of the original data before it is compressed for the export.
  optional int32 original_data_size_kb = 3;

  // Size of the compressed data being exported.
  optional int32 compressed_data_size_kb = 4;

  // The number of export attempts that have failed with the same error code
  // as the current export attempt. It is 0 if the current export is a regular
  // scheduled export rather than a retry.
  optional int32 repeat_error_on_retry_count = 5;
}

/**
 * Tracks when a data import is started or changes status.
 */
message HealthConnectImportInvoked {

  // Status of the import (started/success/failure)
  optional android.healthfitness.api.ImportStatus status = 1;

  // Time taken between the start of the import and its conclusion.
  optional int32 time_to_succeed_or_fail_millis = 2;

  // Size of the original data after it is decompressed after the import.
  optional int32 original_data_size_kb = 3;

  // Size of the compressed data being imported.
  optional int32 compressed_data_size_kb = 4;
}

/**
 * Track when a Backup and Restore data backup is invoked.
 * Logged from:
 * packages/modules/HealthFitness/service/java/com/android/server/healthconnect/logging/BackupRestoreLogger.java
 *
 * Estimated Logging Rate:
 * Avg: 1 per device per day
 */
message HealthConnectDataBackupInvoked {
  // Status of the data backup (started/success/failure)
  optional android.healthfitness.api.DataBackupStatus status = 1;

  /**
   * Time taken between the start of the data backup and its conclusion.
   */
  optional int32 time_to_succeed_or_fail_millis = 2;

  /**
   * Size of the data being backed up.
   * Deprecated as field cannot be populated with data at time of logging.
   */
  optional int32 data_size_kb = 3 [deprecated = true];

  // Data backup type (full/incremental).
  optional android.healthfitness.api.DataBackupType backup_type = 4;

  // Total number of being records backed up.
  optional int32 total_record_count = 5;
}

/**
 * Track when a Backup and Restore metadata backup is invoked.
 * Logged from:
 * packages/modules/HealthFitness/service/java/com/android/server/healthconnect/logging/BackupRestoreLogger.java
 *
 * Estimated Logging Rate:
 * Avg: 1 per device per day
 */
message HealthConnectMetadataBackupInvoked {

  // Status of the metadata backup (started/success/failure)
  optional android.healthfitness.api.MetadataBackupStatus status = 1;

  // Time taken between the start of the metadata backup and its conclusion.
  optional int32 time_to_succeed_or_fail_millis = 2;

  // Size of the metadata being backed up.
  optional int32 metadata_size_kb = 3;
}

/**
 * Track when a Backup and Restore data restore is invoked.
 * Logged from:
 * packages/modules/HealthFitness/service/java/com/android/server/healthconnect/logging/BackupRestoreLogger.java
 *
 * Estimated Logging Rate:
 * Avg: <1 per device per day
 */
message HealthConnectDataRestoreInvoked {

  // Status of the data restore (started/success/failure)
  optional android.healthfitness.api.DataRestoreStatus status = 1;

  // Time taken between the start of the data restore and its conclusion.
  optional int32 time_to_succeed_or_fail_millis = 2;

  /**
   * Size of the data being restored.
   * Deprecated as field cannot be populated with data at time of logging.
   */
  optional int32 data_size_kb = 3 [deprecated = true];

  // Total number of being records restored.
  optional int32 total_record_count = 4;

  // Number of successfully restored records.
  optional int32 successful_record_count = 5;
}

/**
 * Track when a Backup and Restore metadata restore is invoked.
 * Logged from:
 * packages/modules/HealthFitness/service/java/com/android/server/healthconnect/logging/BackupRestoreLogger.java
 *
 * Estimated Logging Rate:
 * Avg: <1 per device per day
 */
message HealthConnectMetadataRestoreInvoked {

  // Status of the metadata restore (started/success/failure)
  optional android.healthfitness.api.MetadataRestoreStatus status = 1;

  // Time taken between the start of the metadata restore and its conclusion.
  optional int32 time_to_succeed_or_fail_millis = 2;

  // Size of the metadata being restored.
  optional int32 metadata_size_kb = 3;
}

// Track when the eligibility of a Backup and Restore restore is checked.
message HealthConnectRestoreEligibilityChecked {
  optional bool is_eligible = 1;
}

// Track Health Connect API operations stats.
message HealthConnectApiInvoked {

  // API method invoked.
  optional android.healthfitness.api.ApiMethod api_method = 1;

  // Status whether the API call executed successfully or not.
  optional android.healthfitness.api.ApiStatus api_status = 2;

  // Only relevant when status == ERROR;
  optional int32 error_code = 3;

  // Total API call duration in milliseconds.
  optional int64 duration_millis = 4;

  // Package name of the client that invoked the API.
  optional string package_name = 5;

  // Data types under consideration in the API call (if any)
  optional android.healthfitness.api.DataType data_type_one = 6
  [(field_restriction_option).health_connect = true];

  optional android.healthfitness.api.DataType data_type_two = 7
  [(field_restriction_option).health_connect = true];

  optional android.healthfitness.api.DataType data_type_three = 8
  [(field_restriction_option).health_connect = true];

  optional android.healthfitness.api.DataType data_type_four = 9
  [(field_restriction_option).health_connect = true];

  optional android.healthfitness.api.DataType data_type_five = 10
  [(field_restriction_option).health_connect = true];

  optional android.healthfitness.api.DataType data_type_six = 11
  [(field_restriction_option).health_connect = true];

}

// Track Health Connect API operations stats.
message HealthConnectPhrApiInvoked {

  // API method invoked.
  optional android.healthfitness.api.ApiMethod api_method = 1;

  // Status whether the API call executed successfully or not.
  optional android.healthfitness.api.ApiStatus api_status = 2;

  // Package name of the client that invoked the API.
  optional string package_name = 3;

  // Medical resource type under consideration in the API call (if any).
  // When there are multiple resource types in an API call, multiple HealthConnectPhrApiInvoked
  // messages will be created and logged.
  optional android.healthfitness.api.MedicalResourceType medical_resource_type = 4
    [(field_restriction_option).health_connect = true];
}

/**
 * Information about a permission granted to each package using HC.
 */
message HealthConnectPermissionStats {

  // Name of package. We will remove any package with less than certain number of installs (500k for now) from aggregations.
  optional string package_name = 1;

  // Health Connect permission granted to the given package
  repeated string permission_name = 2;
}

/**
 * Information about Health Connect Ecosystem for the user.
 */
message HealthConnectEcosystemStats {

  // Datatypes read or written in past 30 days
  repeated android.healthfitness.api.DataType read_or_write = 1;

  // Datatypes read in past 30 days
  repeated android.healthfitness.api.DataType read = 2;

  // Datatypes written in past 30 days
  repeated android.healthfitness.api.DataType write = 3;

  // Datatypes shared in past 30 days
  repeated android.healthfitness.api.DataType shared = 4;

  // Number of apps sharing data
  optional int32 number_of_app_pairings = 5;

}

/**
 * Sensitive Ecosystem metrics being collected via PWW.
 */
message HealthConnectRestrictedEcosystemStats {

  // Package name writing data in directional pairings.
  // First package name alphabetically for non-directional pairings.
  optional string package_name_one = 1;

  // Package name reading data in directional pairings.
  // Second package name alphabetically for non-directional pairings.
  optional string package_name_two = 2;

  // Data type being shared among packages.
  optional android.healthfitness.api.DataType data_type = 3
  [(field_restriction_option).health_connect = true];

  // Enum telling which metric is being represented by the atom.
  optional android.healthfitness.api.MetricType metric_type = 4;

}

/**
 * Latency stats for session data types per package
 */
message HealthConnectLatencyStats {

  // Package name writing data.
  optional string package_name = 1;

  // Data type being written.
  optional android.healthfitness.api.SessionDataType session_data_type = 2;

  // Latency between activity insert and activity end time
  optional int64 latency = 3;

}

/**
 * Metrics for recording methods collected via PWW.
 *
 * Estimated Logging Rate:
 * Peak: ~400 times per week per device (5 pkg * 20 types * 4 methods)
 * Avg: ~20 times per week per device (1 pkg * 5 types * 4 methods)
 */
message HealthConnectRecordingMethodStats {
  // The package name of the application that wrote the data.
  optional string package_name = 1;

  // The data type of the record in question.
  optional android.healthfitness.api.DataType data_type = 2
  [(field_restriction_option).health_connect = true];

  // The specific recording method used to capture the record.
  optional android.healthfitness.api.RecordingMethod recording_method = 3;
}

/**
 * Metrics for device info collected via PWW.
 *
 * Estimated Logging Rate:
 * Peak: ~100 times per week per device (5 pkg * 20 types)
 * Avg: ~5 times per week per device (1 pkg * 5 types)
 */
message HealthConnectDeviceInfoStats {
  // The package name of the application that wrote the data.
  optional string package_name = 1;

  // The data type of the records in question.
  optional android.healthfitness.api.DataType data_type = 2
  [(field_restriction_option).health_connect = true];

  // Whether or not the records from the package of the type have manufacturer set
  optional bool has_manufacturer = 3;

  // Whether or not the records from the package of the type have device model set
  optional bool has_model = 4;

  // Whether or not the records from the package of the type have device type set
  optional bool has_type = 5;
}

/**
 * Metrics for Data Granularity of Non-Sensitive Series Data Type

 * Estimated Logging Rate:
 * Peak: ~60 times per week (5 pkg * 6 types * 2 boolean)
 * Avg: ~12 times per week (1 pkg * 6 types * 2 boolean)
 */
message HealthConnectDataGranularityStats {

  // Package name writing data.
  optional string package_name = 1;

  // Data type being written.
  optional android.healthfitness.api.GranularityDataType granularity_data_type = 2;

  // Average time gap between different records in milliseconds (round to closest long).
  optional int64 granularity = 3;

  // True when granularity being logged is during an active session i.e. while sleep or exercise
  optional android.healthfitness.api.DataState data_state = 4;
}

/**
 * Metrics for native tracking.
 *
 * Estimated Logging Rate: once per day.
 * Logged from: packages/modules/HealthFitness/service/java/com/android/server/healthconnect/common/logging/DailyLoggingService.java
 */
message HealthConnectNativeTrackingStatsReported {
  // Datatypes for which native tracking is currently active.
  repeated android.healthfitness.api.NativeTrackingDataType native_data_types_active = 1;

  // Datatypes for which the user has explicitly turned off native tracking.
  repeated android.healthfitness.api.NativeTrackingDataType native_data_types_disabled = 2;

  // Number of times a record has been written to disk this boot cycle.
  optional int32 number_of_writes = 3;

  // How many seconds have elapsed since the device booted.
  optional int32 uptime_seconds = 4;

  // The last error, if one occurred.
  optional android.healthfitness.api.NativeTrackingErrorCode last_error_code = 5;

  // Number of packages reading steps data.
  optional int32 steps_readers_count = 6;

  // Number of packages writing steps data.
  optional int32 steps_writers_count = 7;
}
