1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.healthconnect.logging; 18 19 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED; 20 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__API_METHOD_UNKNOWN; 21 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__CREATE_MEDICAL_DATA_SOURCE; 22 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_DATA; 23 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_MEDICAL_DATA_SOURCE_WITH_DATA; 24 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_MEDICAL_RESOURCES_BY_IDS; 25 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_MEDICAL_RESOURCES_BY_REQUESTS; 26 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__GET_CHANGES; 27 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__GET_CHANGES_TOKEN; 28 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__GET_GRANTED_PERMISSIONS; 29 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__GET_MEDICAL_DATA_SOURCES_BY_IDS; 30 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__GET_MEDICAL_DATA_SOURCES_BY_REQUESTS; 31 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__INSERT_DATA; 32 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__READ_AGGREGATED_DATA; 33 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__READ_DATA; 34 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__READ_MEDICAL_RESOURCES_BY_IDS; 35 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__READ_MEDICAL_RESOURCES_BY_REQUESTS; 36 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__REVOKE_ALL_PERMISSIONS; 37 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__UPDATE_DATA; 38 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_METHOD__UPSERT_MEDICAL_RESOURCES; 39 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_STATUS__ERROR; 40 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_STATUS__STATUS_UNKNOWN; 41 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__API_STATUS__SUCCESS; 42 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__CALLER_FOREGROUND_STATE__BACKGROUND; 43 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__CALLER_FOREGROUND_STATE__FOREGROUND; 44 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__CALLER_FOREGROUND_STATE__UNSPECIFIED; 45 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__NOT_DEFINED; 46 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__NOT_USED; 47 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_ABOVE_3000; 48 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_BW_1000_TO_2000; 49 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_BW_2000_TO_3000; 50 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_BW_500_TO_1000; 51 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_UNDER_500; 52 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_ABOVE_5000; 53 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_1000_TO_2000; 54 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_2000_TO_3000; 55 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_3000_TO_4000; 56 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_4000_TO_5000; 57 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_UNDER_1000; 58 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_ABOVE_4000; 59 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_BW_1000_TO_2000; 60 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_BW_2000_TO_3000; 61 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_BW_3000_TO_4000; 62 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_UNDER_1000; 63 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_ABOVE_6000; 64 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_2000_TO_3000; 65 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_3000_TO_4000; 66 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_4000_TO_5000; 67 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_5000_TO_6000; 68 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_UNDER_2000; 69 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED; 70 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__ACTIVE_CALORIES_BURNED; 71 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BASAL_BODY_TEMPERATURE; 72 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BASAL_METABOLIC_RATE; 73 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BLOOD_GLUCOSE; 74 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BLOOD_PRESSURE; 75 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BODY_FAT; 76 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BODY_TEMPERATURE; 77 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BODY_WATER_MASS; 78 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BONE_MASS; 79 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__CERVICAL_MUCUS; 80 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__CYCLING_PEDALING_CADENCE; 81 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__DATA_TYPE_NOT_ASSIGNED; 82 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__DATA_TYPE_UNKNOWN; 83 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__DISTANCE; 84 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__ELEVATION_GAINED; 85 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__EXERCISE_SESSION; 86 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__FLOORS_CLIMBED; 87 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HEART_RATE; 88 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HEART_RATE_VARIABILITY_RMSSD; 89 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HEIGHT; 90 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HYDRATION; 91 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__INTERMENSTRUAL_BLEEDING; 92 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__LEAN_BODY_MASS; 93 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__MENSTRUATION_FLOW; 94 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__MENSTRUATION_PERIOD; 95 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__MINDFULNESS_SESSION; 96 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__NUTRITION; 97 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__OVULATION_TEST; 98 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__OXYGEN_SATURATION; 99 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__PLANNED_EXERCISE_SESSION; 100 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__POWER; 101 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__RESPIRATORY_RATE; 102 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__RESTING_HEART_RATE; 103 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SEXUAL_ACTIVITY; 104 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SKIN_TEMPERATURE; 105 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SLEEP_SESSION; 106 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SPEED; 107 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__STEPS; 108 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__STEPS_CADENCE; 109 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__TOTAL_CALORIES_BURNED; 110 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__VO2_MAX; 111 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__WEIGHT; 112 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__WHEELCHAIR_PUSHES; 113 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED; 114 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES; 115 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_CONDITIONS; 116 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_LABORATORY_RESULTS; 117 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_MEDICATIONS; 118 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PERSONAL_DETAILS; 119 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PRACTITIONER_DETAILS; 120 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PREGNANCY; 121 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PROCEDURES; 122 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_SOCIAL_HISTORY; 123 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_UNKNOWN; 124 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_VACCINES; 125 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_VISITS; 126 import static android.health.HealthFitnessStatsLog.HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_VITAL_SIGNS; 127 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES; 128 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_CONDITIONS; 129 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_LABORATORY_RESULTS; 130 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_MEDICATIONS; 131 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_PERSONAL_DETAILS; 132 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_PRACTITIONER_DETAILS; 133 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_PREGNANCY; 134 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_PROCEDURES; 135 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_SOCIAL_HISTORY; 136 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_VACCINES; 137 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_VISITS; 138 import static android.health.connect.datatypes.MedicalResource.MEDICAL_RESOURCE_TYPE_VITAL_SIGNS; 139 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_ACTIVE_CALORIES_BURNED; 140 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BASAL_BODY_TEMPERATURE; 141 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BASAL_METABOLIC_RATE; 142 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BLOOD_GLUCOSE; 143 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BLOOD_PRESSURE; 144 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BODY_FAT; 145 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BODY_TEMPERATURE; 146 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BODY_WATER_MASS; 147 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_BONE_MASS; 148 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_CERVICAL_MUCUS; 149 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_CYCLING_PEDALING_CADENCE; 150 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_DISTANCE; 151 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_ELEVATION_GAINED; 152 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_EXERCISE_SESSION; 153 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_FLOORS_CLIMBED; 154 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_HEART_RATE; 155 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_HEART_RATE_VARIABILITY_RMSSD; 156 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_HEIGHT; 157 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_HYDRATION; 158 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_INTERMENSTRUAL_BLEEDING; 159 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_LEAN_BODY_MASS; 160 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_FLOW; 161 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_PERIOD; 162 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_MINDFULNESS_SESSION; 163 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_NUTRITION; 164 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_OVULATION_TEST; 165 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_OXYGEN_SATURATION; 166 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_PLANNED_EXERCISE_SESSION; 167 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_POWER; 168 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_RESPIRATORY_RATE; 169 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_RESTING_HEART_RATE; 170 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_SEXUAL_ACTIVITY; 171 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_SKIN_TEMPERATURE; 172 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_SLEEP_SESSION; 173 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_SPEED; 174 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_STEPS; 175 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_STEPS_CADENCE; 176 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_TOTAL_CALORIES_BURNED; 177 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_UNKNOWN; 178 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_VO2_MAX; 179 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_WEIGHT; 180 import static android.health.connect.datatypes.RecordTypeIdentifier.RECORD_TYPE_WHEELCHAIR_PUSHES; 181 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_READS_PER_15M_BACKGROUND; 182 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_READS_PER_15M_FOREGROUND; 183 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_READS_PER_24H_BACKGROUND; 184 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_READS_PER_24H_FOREGROUND; 185 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_WRITES_PER_15M_BACKGROUND; 186 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_WRITES_PER_15M_FOREGROUND; 187 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_WRITES_PER_24H_BACKGROUND; 188 import static android.health.connect.ratelimiter.RateLimiter.QuotaBucket.QUOTA_BUCKET_WRITES_PER_24H_FOREGROUND; 189 190 import static com.android.healthfitness.flags.Flags.personalHealthRecordTelemetry; 191 import static com.android.healthfitness.flags.Flags.personalHealthRecordTelemetryPrivateWw; 192 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.CREATE_MEDICAL_DATA_SOURCE; 193 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.DELETE_MEDICAL_DATA_SOURCE_WITH_DATA; 194 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.DELETE_MEDICAL_RESOURCES_BY_IDS; 195 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.DELETE_MEDICAL_RESOURCES_BY_REQUESTS; 196 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.GET_MEDICAL_DATA_SOURCES_BY_IDS; 197 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.GET_MEDICAL_DATA_SOURCES_BY_REQUESTS; 198 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.READ_MEDICAL_RESOURCES_BY_IDS; 199 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.READ_MEDICAL_RESOURCES_BY_REQUESTS; 200 import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.UPSERT_MEDICAL_RESOURCES; 201 202 import android.annotation.IntDef; 203 import android.health.HealthFitnessStatsLog; 204 import android.health.connect.datatypes.MedicalResource; 205 import android.health.connect.internal.datatypes.RecordInternal; 206 import android.health.connect.ratelimiter.RateLimiter; 207 208 import com.android.internal.annotations.VisibleForTesting; 209 import com.android.server.healthconnect.storage.utils.InternalHealthConnectMappings; 210 211 import java.lang.annotation.Retention; 212 import java.lang.annotation.RetentionPolicy; 213 import java.util.ArrayList; 214 import java.util.Arrays; 215 import java.util.HashMap; 216 import java.util.HashSet; 217 import java.util.List; 218 import java.util.Map; 219 import java.util.Map.Entry; 220 import java.util.Objects; 221 import java.util.Set; 222 223 /** 224 * Class to log metrics from HealthConnectService 225 * 226 * @hide 227 */ 228 public class HealthConnectServiceLogger { 229 230 private final HealthFitnessStatsLog mStatsLog; 231 private final int mHealthDataServiceApiMethod; 232 private final int mHealthDataServiceApiStatus; 233 private final int mErrorCode; 234 private final long mDuration; 235 private final boolean mHoldsDataManagementPermission; 236 private final int mRateLimit; 237 private final int mNumberOfRecords; 238 private final int[] mRecordTypes; 239 private Set<Integer> mMedicalResourceTypes; 240 private final String mPackageName; 241 private final int mCallerForegroundState; 242 private static final int MAX_NUMBER_OF_LOGGED_DATA_TYPES = 6; 243 private static final int RECORD_TYPE_NOT_ASSIGNED_DEFAULT_VALUE = -1; 244 245 @VisibleForTesting 246 public static final int MEDICAL_RESOURCE_TYPE_NOT_ASSIGNED_DEFAULT_VALUE = -1; 247 248 /** 249 * HealthConnectService ApiMethods supported by logging. 250 * 251 * @hide 252 */ 253 public static final class ApiMethods { 254 255 public static final int API_METHOD_UNKNOWN = 256 HEALTH_CONNECT_API_CALLED__API_METHOD__API_METHOD_UNKNOWN; 257 public static final int DELETE_DATA = HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_DATA; 258 public static final int GET_CHANGES = HEALTH_CONNECT_API_CALLED__API_METHOD__GET_CHANGES; 259 public static final int GET_CHANGES_TOKEN = 260 HEALTH_CONNECT_API_CALLED__API_METHOD__GET_CHANGES_TOKEN; 261 public static final int GET_GRANTED_PERMISSIONS = 262 HEALTH_CONNECT_API_CALLED__API_METHOD__GET_GRANTED_PERMISSIONS; 263 public static final int INSERT_DATA = HEALTH_CONNECT_API_CALLED__API_METHOD__INSERT_DATA; 264 public static final int READ_AGGREGATED_DATA = 265 HEALTH_CONNECT_API_CALLED__API_METHOD__READ_AGGREGATED_DATA; 266 public static final int READ_DATA = HEALTH_CONNECT_API_CALLED__API_METHOD__READ_DATA; 267 public static final int REVOKE_ALL_PERMISSIONS = 268 HEALTH_CONNECT_API_CALLED__API_METHOD__REVOKE_ALL_PERMISSIONS; 269 public static final int UPDATE_DATA = HEALTH_CONNECT_API_CALLED__API_METHOD__UPDATE_DATA; 270 // PHR data source APIs 271 public static final int CREATE_MEDICAL_DATA_SOURCE = 272 HEALTH_CONNECT_API_CALLED__API_METHOD__CREATE_MEDICAL_DATA_SOURCE; 273 public static final int GET_MEDICAL_DATA_SOURCES_BY_IDS = 274 HEALTH_CONNECT_API_CALLED__API_METHOD__GET_MEDICAL_DATA_SOURCES_BY_IDS; 275 public static final int GET_MEDICAL_DATA_SOURCES_BY_REQUESTS = 276 HEALTH_CONNECT_API_CALLED__API_METHOD__GET_MEDICAL_DATA_SOURCES_BY_REQUESTS; 277 public static final int DELETE_MEDICAL_DATA_SOURCE_WITH_DATA = 278 HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_MEDICAL_DATA_SOURCE_WITH_DATA; 279 // PHR medical resource APIs 280 public static final int UPSERT_MEDICAL_RESOURCES = 281 HEALTH_CONNECT_API_CALLED__API_METHOD__UPSERT_MEDICAL_RESOURCES; 282 public static final int READ_MEDICAL_RESOURCES_BY_IDS = 283 HEALTH_CONNECT_API_CALLED__API_METHOD__READ_MEDICAL_RESOURCES_BY_IDS; 284 public static final int READ_MEDICAL_RESOURCES_BY_REQUESTS = 285 HEALTH_CONNECT_API_CALLED__API_METHOD__READ_MEDICAL_RESOURCES_BY_REQUESTS; 286 public static final int DELETE_MEDICAL_RESOURCES_BY_IDS = 287 HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_MEDICAL_RESOURCES_BY_IDS; 288 public static final int DELETE_MEDICAL_RESOURCES_BY_REQUESTS = 289 HEALTH_CONNECT_API_CALLED__API_METHOD__DELETE_MEDICAL_RESOURCES_BY_REQUESTS; 290 291 @IntDef({ 292 API_METHOD_UNKNOWN, 293 DELETE_DATA, 294 GET_CHANGES, 295 GET_CHANGES_TOKEN, 296 GET_GRANTED_PERMISSIONS, 297 INSERT_DATA, 298 READ_AGGREGATED_DATA, 299 READ_DATA, 300 REVOKE_ALL_PERMISSIONS, 301 UPDATE_DATA, 302 // PHR data source APIs 303 CREATE_MEDICAL_DATA_SOURCE, 304 GET_MEDICAL_DATA_SOURCES_BY_IDS, 305 GET_MEDICAL_DATA_SOURCES_BY_REQUESTS, 306 DELETE_MEDICAL_DATA_SOURCE_WITH_DATA, 307 // PHR medical resource APIs 308 UPSERT_MEDICAL_RESOURCES, 309 READ_MEDICAL_RESOURCES_BY_IDS, 310 READ_MEDICAL_RESOURCES_BY_REQUESTS, 311 DELETE_MEDICAL_RESOURCES_BY_IDS, 312 DELETE_MEDICAL_RESOURCES_BY_REQUESTS 313 }) 314 @Retention(RetentionPolicy.SOURCE) 315 public @interface ApiMethod {} 316 } 317 318 private static final Set<Integer> PHR_APIS = 319 Set.of( 320 // PHR data source APIs 321 CREATE_MEDICAL_DATA_SOURCE, 322 GET_MEDICAL_DATA_SOURCES_BY_IDS, 323 GET_MEDICAL_DATA_SOURCES_BY_REQUESTS, 324 DELETE_MEDICAL_DATA_SOURCE_WITH_DATA, 325 // PHR medical resource APIs 326 UPSERT_MEDICAL_RESOURCES, 327 READ_MEDICAL_RESOURCES_BY_IDS, 328 READ_MEDICAL_RESOURCES_BY_REQUESTS, 329 DELETE_MEDICAL_RESOURCES_BY_IDS, 330 DELETE_MEDICAL_RESOURCES_BY_REQUESTS); 331 332 /** 333 * Rate limiting ranges differentiated by Foreground/Background. 334 * 335 * @hide 336 */ 337 public static final class RateLimitingRanges { 338 339 public static final int NOT_USED = HEALTH_CONNECT_API_CALLED__RATE_LIMIT__NOT_USED; 340 public static final int NOT_DEFINED = HEALTH_CONNECT_API_CALLED__RATE_LIMIT__NOT_DEFINED; 341 public static final int FOREGROUND_15_MIN_UNDER_1000 = 342 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_UNDER_1000; 343 public static final int FOREGROUND_15_MIN_BW_1000_TO_2000 = 344 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_BW_1000_TO_2000; 345 public static final int FOREGROUND_15_MIN_BW_2000_TO_3000 = 346 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_BW_2000_TO_3000; 347 public static final int FOREGROUND_15_MIN_BW_3000_TO_4000 = 348 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_BW_3000_TO_4000; 349 public static final int FOREGROUND_15_MIN_ABOVE_4000 = 350 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_15_MIN_ABOVE_4000; 351 public static final int BACKGROUND_15_MIN_UNDER_500 = 352 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_UNDER_500; 353 public static final int BACKGROUND_15_MIN_BW_500_TO_1000 = 354 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_BW_500_TO_1000; 355 public static final int BACKGROUND_15_MIN_BW_1000_TO_2000 = 356 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_BW_1000_TO_2000; 357 public static final int BACKGROUND_15_MIN_BW_2000_TO_3000 = 358 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_BW_2000_TO_3000; 359 public static final int BACKGROUND_15_MIN_ABOVE_3000 = 360 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_15_MIN_ABOVE_3000; 361 public static final int FOREGROUND_24_HRS_UNDER_2000 = 362 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_UNDER_2000; 363 public static final int FOREGROUND_24_HRS_BW_2000_TO_3000 = 364 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_2000_TO_3000; 365 public static final int FOREGROUND_24_HRS_BW_3000_TO_4000 = 366 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_3000_TO_4000; 367 public static final int FOREGROUND_24_HRS_BW_4000_TO_5000 = 368 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_4000_TO_5000; 369 public static final int FOREGROUND_24_HRS_BW_5000_TO_6000 = 370 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_BW_5000_TO_6000; 371 public static final int FOREGROUND_24_HRS_ABOVE_6000 = 372 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_FOREGROUND_24_HRS_ABOVE_6000; 373 public static final int BACKGROUND_24_HRS_UNDER_1000 = 374 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_UNDER_1000; 375 public static final int BACKGROUND_24_HRS_BW_1000_TO_2000 = 376 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_1000_TO_2000; 377 public static final int BACKGROUND_24_HRS_BW_2000_TO_3000 = 378 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_2000_TO_3000; 379 public static final int BACKGROUND_24_HRS_BW_3000_TO_4000 = 380 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_3000_TO_4000; 381 public static final int BACKGROUND_24_HRS_BW_4000_TO_5000 = 382 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_BW_4000_TO_5000; 383 public static final int BACKGROUND_24_HRS_ABOVE_5000 = 384 HEALTH_CONNECT_API_CALLED__RATE_LIMIT__RATE_LIMIT_BACKGROUND_24_HRS_ABOVE_5000; 385 386 private static final Map<Integer, Integer> sForeground15min = 387 Map.of( 388 0, 389 FOREGROUND_15_MIN_UNDER_1000, 390 1, 391 FOREGROUND_15_MIN_BW_1000_TO_2000, 392 2, 393 BACKGROUND_15_MIN_BW_2000_TO_3000, 394 3, 395 FOREGROUND_15_MIN_BW_3000_TO_4000); 396 397 private static final Map<Integer, Integer> sForeground24hour = 398 Map.of( 399 0, 400 FOREGROUND_24_HRS_UNDER_2000, 401 1, 402 FOREGROUND_24_HRS_UNDER_2000, 403 2, 404 FOREGROUND_24_HRS_BW_2000_TO_3000, 405 3, 406 FOREGROUND_24_HRS_BW_3000_TO_4000, 407 4, 408 FOREGROUND_24_HRS_BW_4000_TO_5000, 409 5, 410 FOREGROUND_24_HRS_BW_5000_TO_6000); 411 412 private static final Map<Integer, Integer> sBackground15Min = 413 Map.of( 414 0, 415 BACKGROUND_15_MIN_BW_500_TO_1000, 416 1, 417 BACKGROUND_15_MIN_BW_1000_TO_2000, 418 2, 419 BACKGROUND_15_MIN_BW_2000_TO_3000); 420 421 private static final Map<Integer, Integer> sBackground24Hour = 422 Map.of( 423 0, 424 BACKGROUND_24_HRS_UNDER_1000, 425 1, 426 BACKGROUND_24_HRS_BW_1000_TO_2000, 427 2, 428 BACKGROUND_24_HRS_BW_2000_TO_3000, 429 3, 430 BACKGROUND_24_HRS_BW_3000_TO_4000, 431 4, 432 BACKGROUND_24_HRS_BW_4000_TO_5000); 433 434 @IntDef({ 435 NOT_USED, 436 FOREGROUND_15_MIN_UNDER_1000, 437 FOREGROUND_15_MIN_BW_1000_TO_2000, 438 FOREGROUND_15_MIN_BW_2000_TO_3000, 439 FOREGROUND_15_MIN_BW_3000_TO_4000, 440 FOREGROUND_15_MIN_ABOVE_4000, 441 BACKGROUND_15_MIN_UNDER_500, 442 BACKGROUND_15_MIN_BW_500_TO_1000, 443 BACKGROUND_15_MIN_BW_1000_TO_2000, 444 BACKGROUND_15_MIN_BW_2000_TO_3000, 445 BACKGROUND_15_MIN_ABOVE_3000, 446 FOREGROUND_24_HRS_UNDER_2000, 447 FOREGROUND_24_HRS_BW_2000_TO_3000, 448 FOREGROUND_24_HRS_BW_3000_TO_4000, 449 FOREGROUND_24_HRS_BW_4000_TO_5000, 450 FOREGROUND_24_HRS_BW_5000_TO_6000, 451 FOREGROUND_24_HRS_ABOVE_6000, 452 BACKGROUND_24_HRS_UNDER_1000, 453 BACKGROUND_24_HRS_BW_1000_TO_2000, 454 BACKGROUND_24_HRS_BW_2000_TO_3000, 455 BACKGROUND_24_HRS_BW_3000_TO_4000, 456 BACKGROUND_24_HRS_BW_4000_TO_5000, 457 BACKGROUND_24_HRS_ABOVE_5000 458 }) 459 @Retention(RetentionPolicy.SOURCE) 460 public @interface RateLimit {} 461 } 462 463 /** 464 * Builder for HealthConnectServiceLogger 465 * 466 * @hide 467 */ 468 public static class Builder { 469 470 private final long mStartTime; 471 private final int mHealthDataServiceApiMethod; 472 private HealthFitnessStatsLog mStatsLog; 473 private int mHealthDataServiceApiStatus; 474 private int mErrorCode; 475 private long mDuration; 476 private int mRateLimit; 477 private int mNumberOfRecords; 478 private final boolean mHoldsDataManagementPermission; 479 private int[] mRecordTypes; 480 private Set<Integer> mMedicalResourceTypes; 481 private String mPackageName; 482 private int mCallerForegroundState; 483 Builder(boolean holdsDataManagementPermission, @ApiMethods.ApiMethod int apiMethod)484 public Builder(boolean holdsDataManagementPermission, @ApiMethods.ApiMethod int apiMethod) { 485 mStatsLog = new HealthFitnessStatsLog(); 486 mStartTime = System.currentTimeMillis(); 487 mHealthDataServiceApiMethod = apiMethod; 488 mHealthDataServiceApiStatus = HEALTH_CONNECT_API_CALLED__API_STATUS__STATUS_UNKNOWN; 489 mErrorCode = 0; // Means no error 490 mHoldsDataManagementPermission = holdsDataManagementPermission; 491 mRateLimit = RateLimitingRanges.NOT_USED; 492 mNumberOfRecords = 0; 493 mRecordTypes = new int[MAX_NUMBER_OF_LOGGED_DATA_TYPES]; 494 Arrays.fill(mRecordTypes, RECORD_TYPE_NOT_ASSIGNED_DEFAULT_VALUE); 495 mMedicalResourceTypes = new HashSet<>(); 496 mPackageName = "UNKNOWN"; 497 mCallerForegroundState = 498 HEALTH_CONNECT_API_CALLED__CALLER_FOREGROUND_STATE__UNSPECIFIED; 499 } 500 501 /** Set the class to write logs to. */ setHealthFitnessStatsLog(HealthFitnessStatsLog logger)502 public Builder setHealthFitnessStatsLog(HealthFitnessStatsLog logger) { 503 mStatsLog = logger; 504 return this; 505 } 506 507 /** Set the API was called successfully. */ setHealthDataServiceApiStatusSuccess()508 public Builder setHealthDataServiceApiStatusSuccess() { 509 this.mHealthDataServiceApiStatus = HEALTH_CONNECT_API_CALLED__API_STATUS__SUCCESS; 510 return this; 511 } 512 513 /** 514 * Set the API threw error. 515 * 516 * @param errorCode Error code thrown by the API. 517 */ setHealthDataServiceApiStatusError(int errorCode)518 public Builder setHealthDataServiceApiStatusError(int errorCode) { 519 this.mErrorCode = errorCode; 520 this.mHealthDataServiceApiStatus = HEALTH_CONNECT_API_CALLED__API_STATUS__ERROR; 521 return this; 522 } 523 524 /** 525 * Set the rate limiting range if used. 526 * 527 * @param quotaBucket Quota bucket. 528 * @param quotaLimit Bucket limit. 529 */ setRateLimit( @ateLimiter.QuotaBucket.Type int quotaBucket, float quotaLimit)530 public Builder setRateLimit( 531 @RateLimiter.QuotaBucket.Type int quotaBucket, float quotaLimit) { 532 this.mRateLimit = calculateRateLimitEnum(quotaBucket, quotaLimit); 533 return this; 534 } 535 536 /** 537 * Set the number of records involved in the API call. 538 * 539 * @param numberOfRecords Number of records. 540 */ setNumberOfRecords(int numberOfRecords)541 public Builder setNumberOfRecords(int numberOfRecords) { 542 this.mNumberOfRecords = numberOfRecords; 543 return this; 544 } 545 546 /** 547 * Set the types of records. 548 * 549 * @param recordInternals List of records. 550 */ setDataTypesFromRecordInternals(List<RecordInternal<?>> recordInternals)551 public Builder setDataTypesFromRecordInternals(List<RecordInternal<?>> recordInternals) { 552 Objects.requireNonNull(recordInternals); 553 Map<Integer, Integer> recordTypeToNumberOfRecords = new HashMap<>(); 554 for (RecordInternal<?> recordInternal : recordInternals) { 555 int recordType = getDataTypeEnumFromRecordType(recordInternal.getRecordType()); 556 int numberOfRecords = recordTypeToNumberOfRecords.getOrDefault(recordType, 0); 557 numberOfRecords++; 558 recordTypeToNumberOfRecords.put(recordType, numberOfRecords); 559 } 560 List<Entry<Integer, Integer>> recordTypeSortedByNumberOfRecords = 561 new ArrayList<>(recordTypeToNumberOfRecords.entrySet()); 562 recordTypeSortedByNumberOfRecords.sort(Entry.comparingByValue()); 563 for (int i = 0; 564 i 565 < Math.min( 566 recordTypeSortedByNumberOfRecords.size(), 567 MAX_NUMBER_OF_LOGGED_DATA_TYPES); 568 i++) { 569 mRecordTypes[i] = recordTypeSortedByNumberOfRecords.get(i).getKey(); 570 } 571 return this; 572 } 573 574 /** Sets medical resource types to be logged. */ setMedicalResourceTypes(Set<Integer> medicalResourceTypes)575 public Builder setMedicalResourceTypes(Set<Integer> medicalResourceTypes) { 576 mMedicalResourceTypes = new HashSet<>(medicalResourceTypes); 577 return this; 578 } 579 580 /** 581 * Set the types of records. 582 * 583 * @param recordTypesList List of record types. 584 */ setDataTypesFromRecordTypes(List<Integer> recordTypesList)585 public Builder setDataTypesFromRecordTypes(List<Integer> recordTypesList) { 586 if (recordTypesList == null || recordTypesList.size() == 0) { 587 return this; 588 } 589 HashSet<Integer> recordTypes = new HashSet<>(); 590 for (Integer recordType : recordTypesList) { 591 recordTypes.add(getDataTypeEnumFromRecordType(recordType)); 592 } 593 594 int index = 0; 595 for (int recordType : recordTypes) { 596 mRecordTypes[index++] = recordType; 597 if (index == MAX_NUMBER_OF_LOGGED_DATA_TYPES) { 598 break; 599 } 600 } 601 return this; 602 } 603 604 /** 605 * Set the types of records. 606 * 607 * @param packageName Package name of the caller. 608 */ setPackageName(String packageName)609 public Builder setPackageName(String packageName) { 610 if (packageName == null || packageName.isBlank()) { 611 return this; 612 } 613 mPackageName = packageName; 614 return this; 615 } 616 617 /** 618 * Sets the caller's foreground state. 619 * 620 * @param isCallerInForeground whether the caller is in foreground or background. 621 */ setCallerForegroundState(boolean isCallerInForeground)622 public Builder setCallerForegroundState(boolean isCallerInForeground) { 623 mCallerForegroundState = 624 isCallerInForeground 625 ? HEALTH_CONNECT_API_CALLED__CALLER_FOREGROUND_STATE__FOREGROUND 626 : HEALTH_CONNECT_API_CALLED__CALLER_FOREGROUND_STATE__BACKGROUND; 627 return this; 628 } 629 630 /** Returns an object of {@link HealthConnectServiceLogger}. */ build()631 public HealthConnectServiceLogger build() { 632 mDuration = System.currentTimeMillis() - mStartTime; 633 return new HealthConnectServiceLogger(this); 634 } 635 calculateRateLimitEnum( @ateLimiter.QuotaBucket.Type int quotaBucket, float quotaLimit)636 private int calculateRateLimitEnum( 637 @RateLimiter.QuotaBucket.Type int quotaBucket, float quotaLimit) { 638 int quotient = (int) (quotaLimit / 1000); 639 switch (quotaBucket) { 640 case QUOTA_BUCKET_READS_PER_15M_FOREGROUND: 641 case QUOTA_BUCKET_WRITES_PER_15M_FOREGROUND: 642 return RateLimitingRanges.sForeground15min.getOrDefault( 643 quotient, RateLimitingRanges.FOREGROUND_15_MIN_ABOVE_4000); 644 case QUOTA_BUCKET_READS_PER_24H_FOREGROUND: 645 case QUOTA_BUCKET_WRITES_PER_24H_FOREGROUND: 646 return RateLimitingRanges.sForeground24hour.getOrDefault( 647 quotient, RateLimitingRanges.FOREGROUND_24_HRS_ABOVE_6000); 648 case QUOTA_BUCKET_READS_PER_15M_BACKGROUND: 649 case QUOTA_BUCKET_WRITES_PER_15M_BACKGROUND: 650 if (quotaLimit < 500) { 651 return RateLimitingRanges.BACKGROUND_15_MIN_UNDER_500; 652 } 653 return RateLimitingRanges.sBackground15Min.getOrDefault( 654 quotient, RateLimitingRanges.BACKGROUND_15_MIN_ABOVE_3000); 655 case QUOTA_BUCKET_READS_PER_24H_BACKGROUND: 656 case QUOTA_BUCKET_WRITES_PER_24H_BACKGROUND: 657 return RateLimitingRanges.sBackground24Hour.getOrDefault( 658 quotient, RateLimitingRanges.BACKGROUND_24_HRS_ABOVE_5000); 659 } 660 return RateLimitingRanges.NOT_DEFINED; 661 } 662 663 /** 664 * Public so that it can be used by {@link InternalHealthConnectMappings}. 665 * 666 * @deprecated Use {@link InternalHealthConnectMappings#getLoggingEnumForRecordTypeId(int)}. 667 */ 668 @Deprecated getDataTypeEnumFromRecordType(int recordType)669 public static int getDataTypeEnumFromRecordType(int recordType) { 670 switch (recordType) { 671 case RECORD_TYPE_STEPS: 672 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__STEPS; 673 case RECORD_TYPE_HEART_RATE: 674 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HEART_RATE; 675 case RECORD_TYPE_BASAL_METABOLIC_RATE: 676 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BASAL_METABOLIC_RATE; 677 case RECORD_TYPE_CYCLING_PEDALING_CADENCE: 678 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__CYCLING_PEDALING_CADENCE; 679 case RECORD_TYPE_POWER: 680 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__POWER; 681 case RECORD_TYPE_SPEED: 682 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SPEED; 683 case RECORD_TYPE_STEPS_CADENCE: 684 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__STEPS_CADENCE; 685 case RECORD_TYPE_DISTANCE: 686 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__DISTANCE; 687 case RECORD_TYPE_WHEELCHAIR_PUSHES: 688 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__WHEELCHAIR_PUSHES; 689 case RECORD_TYPE_TOTAL_CALORIES_BURNED: 690 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__TOTAL_CALORIES_BURNED; 691 case RECORD_TYPE_FLOORS_CLIMBED: 692 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__FLOORS_CLIMBED; 693 case RECORD_TYPE_ELEVATION_GAINED: 694 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__ELEVATION_GAINED; 695 case RECORD_TYPE_ACTIVE_CALORIES_BURNED: 696 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__ACTIVE_CALORIES_BURNED; 697 case RECORD_TYPE_HYDRATION: 698 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HYDRATION; 699 case RECORD_TYPE_NUTRITION: 700 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__NUTRITION; 701 case RECORD_TYPE_RESPIRATORY_RATE: 702 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__RESPIRATORY_RATE; 703 case RECORD_TYPE_BONE_MASS: 704 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BONE_MASS; 705 case RECORD_TYPE_RESTING_HEART_RATE: 706 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__RESTING_HEART_RATE; 707 case RECORD_TYPE_BODY_FAT: 708 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BODY_FAT; 709 case RECORD_TYPE_VO2_MAX: 710 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__VO2_MAX; 711 case RECORD_TYPE_CERVICAL_MUCUS: 712 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__CERVICAL_MUCUS; 713 case RECORD_TYPE_BASAL_BODY_TEMPERATURE: 714 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BASAL_BODY_TEMPERATURE; 715 case RECORD_TYPE_MENSTRUATION_FLOW: 716 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__MENSTRUATION_FLOW; 717 case RECORD_TYPE_OXYGEN_SATURATION: 718 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__OXYGEN_SATURATION; 719 case RECORD_TYPE_BLOOD_PRESSURE: 720 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BLOOD_PRESSURE; 721 case RECORD_TYPE_HEIGHT: 722 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HEIGHT; 723 case RECORD_TYPE_BLOOD_GLUCOSE: 724 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BLOOD_GLUCOSE; 725 case RECORD_TYPE_WEIGHT: 726 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__WEIGHT; 727 case RECORD_TYPE_LEAN_BODY_MASS: 728 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__LEAN_BODY_MASS; 729 case RECORD_TYPE_SEXUAL_ACTIVITY: 730 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SEXUAL_ACTIVITY; 731 case RECORD_TYPE_BODY_TEMPERATURE: 732 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BODY_TEMPERATURE; 733 case RECORD_TYPE_OVULATION_TEST: 734 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__OVULATION_TEST; 735 case RECORD_TYPE_EXERCISE_SESSION: 736 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__EXERCISE_SESSION; 737 case RECORD_TYPE_SKIN_TEMPERATURE: 738 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SKIN_TEMPERATURE; 739 case RECORD_TYPE_PLANNED_EXERCISE_SESSION: 740 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__PLANNED_EXERCISE_SESSION; 741 case RECORD_TYPE_MINDFULNESS_SESSION: 742 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__MINDFULNESS_SESSION; 743 case RECORD_TYPE_BODY_WATER_MASS: 744 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__BODY_WATER_MASS; 745 case RECORD_TYPE_HEART_RATE_VARIABILITY_RMSSD: 746 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__HEART_RATE_VARIABILITY_RMSSD; 747 case RECORD_TYPE_INTERMENSTRUAL_BLEEDING: 748 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__INTERMENSTRUAL_BLEEDING; 749 case RECORD_TYPE_MENSTRUATION_PERIOD: 750 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__MENSTRUATION_PERIOD; 751 case RECORD_TYPE_SLEEP_SESSION: 752 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__SLEEP_SESSION; 753 case RECORD_TYPE_UNKNOWN: 754 default: 755 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__DATA_TYPE_UNKNOWN; 756 } 757 } 758 } 759 HealthConnectServiceLogger(HealthConnectServiceLogger.Builder builder)760 private HealthConnectServiceLogger(HealthConnectServiceLogger.Builder builder) { 761 Objects.requireNonNull(builder); 762 763 mHealthDataServiceApiMethod = builder.mHealthDataServiceApiMethod; 764 mHealthDataServiceApiStatus = builder.mHealthDataServiceApiStatus; 765 mErrorCode = builder.mErrorCode; 766 mDuration = builder.mDuration; 767 mHoldsDataManagementPermission = builder.mHoldsDataManagementPermission; 768 mRateLimit = builder.mRateLimit; 769 mNumberOfRecords = builder.mNumberOfRecords; 770 mRecordTypes = builder.mRecordTypes; 771 mMedicalResourceTypes = builder.mMedicalResourceTypes; 772 mPackageName = builder.mPackageName; 773 mCallerForegroundState = builder.mCallerForegroundState; 774 mStatsLog = builder.mStatsLog; 775 } 776 777 /** Log to statsd. */ log()778 public void log() { 779 // Do not log API calls made from the controller 780 if (mHoldsDataManagementPermission) { 781 return; 782 } 783 784 boolean isPhrApi = PHR_APIS.contains(mHealthDataServiceApiMethod); 785 if (isPhrApi) { 786 writePhrLogs(); 787 return; 788 } 789 790 mStatsLog.write( 791 HEALTH_CONNECT_API_CALLED, 792 mHealthDataServiceApiMethod, 793 mHealthDataServiceApiStatus, 794 mErrorCode, 795 mDuration, 796 mNumberOfRecords, 797 mRateLimit, 798 mCallerForegroundState, 799 mPackageName); 800 801 // For private logging, max 6 data types per request are being logged 802 // rest will be ignored 803 mStatsLog.write( 804 HEALTH_CONNECT_API_INVOKED, 805 mHealthDataServiceApiMethod, 806 mHealthDataServiceApiStatus, 807 mErrorCode, 808 mDuration, 809 mPackageName, 810 getRecordTypeEnumToLog(mRecordTypes, 0), 811 getRecordTypeEnumToLog(mRecordTypes, 1), 812 getRecordTypeEnumToLog(mRecordTypes, 2), 813 getRecordTypeEnumToLog(mRecordTypes, 3), 814 getRecordTypeEnumToLog(mRecordTypes, 4), 815 getRecordTypeEnumToLog(mRecordTypes, 5)); 816 } 817 writePhrLogs()818 private void writePhrLogs() { 819 if (personalHealthRecordTelemetry()) { // normal WW 820 mStatsLog.write( 821 HEALTH_CONNECT_API_CALLED, 822 mHealthDataServiceApiMethod, 823 mHealthDataServiceApiStatus, 824 mErrorCode, 825 mDuration, 826 mNumberOfRecords, 827 mRateLimit, 828 mCallerForegroundState, 829 mPackageName); 830 } 831 832 if (personalHealthRecordTelemetryPrivateWw()) { // private WW 833 if (mMedicalResourceTypes.isEmpty()) { 834 writePhrApiInvoked(MEDICAL_RESOURCE_TYPE_NOT_ASSIGNED_DEFAULT_VALUE); 835 } else { 836 for (int medicalResourceType : mMedicalResourceTypes) { 837 writePhrApiInvoked(getMedicalResourceTypeLoggingEnum(medicalResourceType)); 838 } 839 } 840 } 841 } 842 writePhrApiInvoked(int medicalResourceTypeLoggingEnum)843 private void writePhrApiInvoked(int medicalResourceTypeLoggingEnum) { 844 mStatsLog.write( 845 HEALTH_CONNECT_PHR_API_INVOKED, 846 mHealthDataServiceApiMethod, 847 mHealthDataServiceApiStatus, 848 mPackageName, 849 medicalResourceTypeLoggingEnum); 850 } 851 getMedicalResourceTypeLoggingEnum( @edicalResource.MedicalResourceType int medicalResourceType)852 private static int getMedicalResourceTypeLoggingEnum( 853 @MedicalResource.MedicalResourceType int medicalResourceType) { 854 return switch (medicalResourceType) { 855 case MEDICAL_RESOURCE_TYPE_VACCINES -> 856 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_VACCINES; 857 case MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES -> 858 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_ALLERGIES_INTOLERANCES; 859 case MEDICAL_RESOURCE_TYPE_PREGNANCY -> 860 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PREGNANCY; 861 case MEDICAL_RESOURCE_TYPE_SOCIAL_HISTORY -> 862 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_SOCIAL_HISTORY; 863 case MEDICAL_RESOURCE_TYPE_VITAL_SIGNS -> 864 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_VITAL_SIGNS; 865 case MEDICAL_RESOURCE_TYPE_LABORATORY_RESULTS -> 866 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_LABORATORY_RESULTS; 867 case MEDICAL_RESOURCE_TYPE_CONDITIONS -> 868 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_CONDITIONS; 869 case MEDICAL_RESOURCE_TYPE_PROCEDURES -> 870 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PROCEDURES; 871 case MEDICAL_RESOURCE_TYPE_MEDICATIONS -> 872 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_MEDICATIONS; 873 case MEDICAL_RESOURCE_TYPE_PERSONAL_DETAILS -> 874 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PERSONAL_DETAILS; 875 case MEDICAL_RESOURCE_TYPE_PRACTITIONER_DETAILS -> 876 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_PRACTITIONER_DETAILS; 877 case MEDICAL_RESOURCE_TYPE_VISITS -> 878 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_VISITS; 879 default -> 880 HEALTH_CONNECT_PHR_API_INVOKED__MEDICAL_RESOURCE_TYPE__MEDICAL_RESOURCE_TYPE_UNKNOWN; 881 }; 882 } 883 getRecordTypeEnumToLog(int[] recordTypes, int index)884 private int getRecordTypeEnumToLog(int[] recordTypes, int index) { 885 if (recordTypes[index] == RECORD_TYPE_NOT_ASSIGNED_DEFAULT_VALUE) { 886 return HEALTH_CONNECT_API_INVOKED__DATA_TYPE_ONE__DATA_TYPE_NOT_ASSIGNED; 887 } 888 return recordTypes[index]; 889 } 890 } 891