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 android.health.connect.internal.datatypes.utils; 18 19 import android.annotation.NonNull; 20 import android.health.connect.datatypes.ActiveCaloriesBurnedRecord; 21 import android.health.connect.datatypes.BasalBodyTemperatureRecord; 22 import android.health.connect.datatypes.BasalMetabolicRateRecord; 23 import android.health.connect.datatypes.BloodGlucoseRecord; 24 import android.health.connect.datatypes.BloodPressureRecord; 25 import android.health.connect.datatypes.BodyFatRecord; 26 import android.health.connect.datatypes.BodyTemperatureRecord; 27 import android.health.connect.datatypes.BodyWaterMassRecord; 28 import android.health.connect.datatypes.BoneMassRecord; 29 import android.health.connect.datatypes.CervicalMucusRecord; 30 import android.health.connect.datatypes.CyclingPedalingCadenceRecord; 31 import android.health.connect.datatypes.DistanceRecord; 32 import android.health.connect.datatypes.ElevationGainedRecord; 33 import android.health.connect.datatypes.ExerciseSessionRecord; 34 import android.health.connect.datatypes.FloorsClimbedRecord; 35 import android.health.connect.datatypes.HeartRateRecord; 36 import android.health.connect.datatypes.HeartRateVariabilityRmssdRecord; 37 import android.health.connect.datatypes.HeightRecord; 38 import android.health.connect.datatypes.HydrationRecord; 39 import android.health.connect.datatypes.IntermenstrualBleedingRecord; 40 import android.health.connect.datatypes.LeanBodyMassRecord; 41 import android.health.connect.datatypes.MenstruationFlowRecord; 42 import android.health.connect.datatypes.MenstruationPeriodRecord; 43 import android.health.connect.datatypes.NutritionRecord; 44 import android.health.connect.datatypes.OvulationTestRecord; 45 import android.health.connect.datatypes.OxygenSaturationRecord; 46 import android.health.connect.datatypes.PlannedExerciseSessionRecord; 47 import android.health.connect.datatypes.PowerRecord; 48 import android.health.connect.datatypes.Record; 49 import android.health.connect.datatypes.RecordTypeIdentifier; 50 import android.health.connect.datatypes.RespiratoryRateRecord; 51 import android.health.connect.datatypes.RestingHeartRateRecord; 52 import android.health.connect.datatypes.SexualActivityRecord; 53 import android.health.connect.datatypes.SkinTemperatureRecord; 54 import android.health.connect.datatypes.SleepSessionRecord; 55 import android.health.connect.datatypes.SpeedRecord; 56 import android.health.connect.datatypes.StepsCadenceRecord; 57 import android.health.connect.datatypes.StepsRecord; 58 import android.health.connect.datatypes.TotalCaloriesBurnedRecord; 59 import android.health.connect.datatypes.Vo2MaxRecord; 60 import android.health.connect.datatypes.WeightRecord; 61 import android.health.connect.datatypes.WheelchairPushesRecord; 62 import android.health.connect.internal.datatypes.ActiveCaloriesBurnedRecordInternal; 63 import android.health.connect.internal.datatypes.BasalBodyTemperatureRecordInternal; 64 import android.health.connect.internal.datatypes.BasalMetabolicRateRecordInternal; 65 import android.health.connect.internal.datatypes.BloodGlucoseRecordInternal; 66 import android.health.connect.internal.datatypes.BloodPressureRecordInternal; 67 import android.health.connect.internal.datatypes.BodyFatRecordInternal; 68 import android.health.connect.internal.datatypes.BodyTemperatureRecordInternal; 69 import android.health.connect.internal.datatypes.BodyWaterMassRecordInternal; 70 import android.health.connect.internal.datatypes.BoneMassRecordInternal; 71 import android.health.connect.internal.datatypes.CervicalMucusRecordInternal; 72 import android.health.connect.internal.datatypes.CyclingPedalingCadenceRecordInternal; 73 import android.health.connect.internal.datatypes.DistanceRecordInternal; 74 import android.health.connect.internal.datatypes.ElevationGainedRecordInternal; 75 import android.health.connect.internal.datatypes.ExerciseSessionRecordInternal; 76 import android.health.connect.internal.datatypes.FloorsClimbedRecordInternal; 77 import android.health.connect.internal.datatypes.HeartRateRecordInternal; 78 import android.health.connect.internal.datatypes.HeartRateVariabilityRmssdRecordInternal; 79 import android.health.connect.internal.datatypes.HeightRecordInternal; 80 import android.health.connect.internal.datatypes.HydrationRecordInternal; 81 import android.health.connect.internal.datatypes.IntermenstrualBleedingRecordInternal; 82 import android.health.connect.internal.datatypes.LeanBodyMassRecordInternal; 83 import android.health.connect.internal.datatypes.MenstruationFlowRecordInternal; 84 import android.health.connect.internal.datatypes.MenstruationPeriodRecordInternal; 85 import android.health.connect.internal.datatypes.NutritionRecordInternal; 86 import android.health.connect.internal.datatypes.OvulationTestRecordInternal; 87 import android.health.connect.internal.datatypes.OxygenSaturationRecordInternal; 88 import android.health.connect.internal.datatypes.PlannedExerciseSessionRecordInternal; 89 import android.health.connect.internal.datatypes.PowerRecordInternal; 90 import android.health.connect.internal.datatypes.RecordInternal; 91 import android.health.connect.internal.datatypes.RespiratoryRateRecordInternal; 92 import android.health.connect.internal.datatypes.RestingHeartRateRecordInternal; 93 import android.health.connect.internal.datatypes.SexualActivityRecordInternal; 94 import android.health.connect.internal.datatypes.SkinTemperatureRecordInternal; 95 import android.health.connect.internal.datatypes.SleepSessionRecordInternal; 96 import android.health.connect.internal.datatypes.SpeedRecordInternal; 97 import android.health.connect.internal.datatypes.StepsCadenceRecordInternal; 98 import android.health.connect.internal.datatypes.StepsRecordInternal; 99 import android.health.connect.internal.datatypes.TotalCaloriesBurnedRecordInternal; 100 import android.health.connect.internal.datatypes.Vo2MaxRecordInternal; 101 import android.health.connect.internal.datatypes.WeightRecordInternal; 102 import android.health.connect.internal.datatypes.WheelchairPushesRecordInternal; 103 import android.util.ArrayMap; 104 105 import java.util.Map; 106 107 /** @hide */ 108 public final class RecordMapper { 109 private static final int NUM_ENTRIES = 35; 110 111 @SuppressWarnings("NullAway.Init") // TODO(b/317029272): fix this suppression 112 private static volatile RecordMapper sRecordMapper; 113 114 private final Map<Integer, Class<? extends RecordInternal<?>>> 115 mRecordIdToInternalRecordClassMap; 116 private final Map<Integer, Class<? extends Record>> mRecordIdToExternalRecordClassMap; 117 private final Map<Class<? extends Record>, Integer> mExternalRecordClassToRecordIdMap; 118 RecordMapper()119 private RecordMapper() { 120 mRecordIdToInternalRecordClassMap = new ArrayMap<>(NUM_ENTRIES); 121 mRecordIdToInternalRecordClassMap.put( 122 RecordTypeIdentifier.RECORD_TYPE_STEPS, StepsRecordInternal.class); 123 mRecordIdToInternalRecordClassMap.put( 124 RecordTypeIdentifier.RECORD_TYPE_HEART_RATE, HeartRateRecordInternal.class); 125 mRecordIdToInternalRecordClassMap.put( 126 RecordTypeIdentifier.RECORD_TYPE_FLOORS_CLIMBED, FloorsClimbedRecordInternal.class); 127 mRecordIdToInternalRecordClassMap.put( 128 RecordTypeIdentifier.RECORD_TYPE_HYDRATION, HydrationRecordInternal.class); 129 mRecordIdToInternalRecordClassMap.put( 130 RecordTypeIdentifier.RECORD_TYPE_ACTIVE_CALORIES_BURNED, 131 ActiveCaloriesBurnedRecordInternal.class); 132 mRecordIdToInternalRecordClassMap.put( 133 RecordTypeIdentifier.RECORD_TYPE_ELEVATION_GAINED, 134 ElevationGainedRecordInternal.class); 135 136 mRecordIdToInternalRecordClassMap.put( 137 RecordTypeIdentifier.RECORD_TYPE_WHEELCHAIR_PUSHES, 138 WheelchairPushesRecordInternal.class); 139 140 mRecordIdToInternalRecordClassMap.put( 141 RecordTypeIdentifier.RECORD_TYPE_TOTAL_CALORIES_BURNED, 142 TotalCaloriesBurnedRecordInternal.class); 143 144 mRecordIdToInternalRecordClassMap.put( 145 RecordTypeIdentifier.RECORD_TYPE_DISTANCE, DistanceRecordInternal.class); 146 mRecordIdToInternalRecordClassMap.put( 147 RecordTypeIdentifier.RECORD_TYPE_BASAL_METABOLIC_RATE, 148 BasalMetabolicRateRecordInternal.class); 149 mRecordIdToInternalRecordClassMap.put( 150 RecordTypeIdentifier.RECORD_TYPE_CYCLING_PEDALING_CADENCE, 151 CyclingPedalingCadenceRecordInternal.class); 152 mRecordIdToInternalRecordClassMap.put( 153 RecordTypeIdentifier.RECORD_TYPE_POWER, PowerRecordInternal.class); 154 mRecordIdToInternalRecordClassMap.put( 155 RecordTypeIdentifier.RECORD_TYPE_NUTRITION, NutritionRecordInternal.class); 156 mRecordIdToInternalRecordClassMap.put( 157 RecordTypeIdentifier.RECORD_TYPE_SPEED, SpeedRecordInternal.class); 158 mRecordIdToInternalRecordClassMap.put( 159 RecordTypeIdentifier.RECORD_TYPE_STEPS_CADENCE, StepsCadenceRecordInternal.class); 160 mRecordIdToInternalRecordClassMap.put( 161 RecordTypeIdentifier.RECORD_TYPE_BODY_WATER_MASS, 162 BodyWaterMassRecordInternal.class); 163 mRecordIdToInternalRecordClassMap.put( 164 RecordTypeIdentifier.RECORD_TYPE_HEART_RATE_VARIABILITY_RMSSD, 165 HeartRateVariabilityRmssdRecordInternal.class); 166 mRecordIdToInternalRecordClassMap.put( 167 RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_PERIOD, 168 MenstruationPeriodRecordInternal.class); 169 mRecordIdToInternalRecordClassMap.put( 170 RecordTypeIdentifier.RECORD_TYPE_INTERMENSTRUAL_BLEEDING, 171 IntermenstrualBleedingRecordInternal.class); 172 173 mRecordIdToInternalRecordClassMap.put( 174 RecordTypeIdentifier.RECORD_TYPE_VO2_MAX, Vo2MaxRecordInternal.class); 175 mRecordIdToInternalRecordClassMap.put( 176 RecordTypeIdentifier.RECORD_TYPE_SEXUAL_ACTIVITY, 177 SexualActivityRecordInternal.class); 178 mRecordIdToInternalRecordClassMap.put( 179 RecordTypeIdentifier.RECORD_TYPE_RESTING_HEART_RATE, 180 RestingHeartRateRecordInternal.class); 181 mRecordIdToInternalRecordClassMap.put( 182 RecordTypeIdentifier.RECORD_TYPE_WEIGHT, WeightRecordInternal.class); 183 mRecordIdToInternalRecordClassMap.put( 184 RecordTypeIdentifier.RECORD_TYPE_OXYGEN_SATURATION, 185 OxygenSaturationRecordInternal.class); 186 mRecordIdToInternalRecordClassMap.put( 187 RecordTypeIdentifier.RECORD_TYPE_RESPIRATORY_RATE, 188 RespiratoryRateRecordInternal.class); 189 mRecordIdToInternalRecordClassMap.put( 190 RecordTypeIdentifier.RECORD_TYPE_BODY_TEMPERATURE, 191 BodyTemperatureRecordInternal.class); 192 mRecordIdToInternalRecordClassMap.put( 193 RecordTypeIdentifier.RECORD_TYPE_BONE_MASS, BoneMassRecordInternal.class); 194 mRecordIdToInternalRecordClassMap.put( 195 RecordTypeIdentifier.RECORD_TYPE_BLOOD_PRESSURE, BloodPressureRecordInternal.class); 196 mRecordIdToInternalRecordClassMap.put( 197 RecordTypeIdentifier.RECORD_TYPE_BODY_FAT, BodyFatRecordInternal.class); 198 mRecordIdToInternalRecordClassMap.put( 199 RecordTypeIdentifier.RECORD_TYPE_BLOOD_GLUCOSE, BloodGlucoseRecordInternal.class); 200 mRecordIdToInternalRecordClassMap.put( 201 RecordTypeIdentifier.RECORD_TYPE_BASAL_BODY_TEMPERATURE, 202 BasalBodyTemperatureRecordInternal.class); 203 mRecordIdToInternalRecordClassMap.put( 204 RecordTypeIdentifier.RECORD_TYPE_OVULATION_TEST, OvulationTestRecordInternal.class); 205 mRecordIdToInternalRecordClassMap.put( 206 RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_FLOW, 207 MenstruationFlowRecordInternal.class); 208 mRecordIdToInternalRecordClassMap.put( 209 RecordTypeIdentifier.RECORD_TYPE_CERVICAL_MUCUS, CervicalMucusRecordInternal.class); 210 mRecordIdToInternalRecordClassMap.put( 211 RecordTypeIdentifier.RECORD_TYPE_HEIGHT, HeightRecordInternal.class); 212 mRecordIdToInternalRecordClassMap.put( 213 RecordTypeIdentifier.RECORD_TYPE_LEAN_BODY_MASS, LeanBodyMassRecordInternal.class); 214 mRecordIdToInternalRecordClassMap.put( 215 RecordTypeIdentifier.RECORD_TYPE_EXERCISE_SESSION, 216 ExerciseSessionRecordInternal.class); 217 mRecordIdToInternalRecordClassMap.put( 218 RecordTypeIdentifier.RECORD_TYPE_PLANNED_EXERCISE_SESSION, 219 PlannedExerciseSessionRecordInternal.class); 220 mRecordIdToInternalRecordClassMap.put( 221 RecordTypeIdentifier.RECORD_TYPE_SLEEP_SESSION, SleepSessionRecordInternal.class); 222 mRecordIdToInternalRecordClassMap.put( 223 RecordTypeIdentifier.RECORD_TYPE_SKIN_TEMPERATURE, 224 SkinTemperatureRecordInternal.class); 225 226 mRecordIdToExternalRecordClassMap = new ArrayMap<>(NUM_ENTRIES); 227 mRecordIdToExternalRecordClassMap.put( 228 RecordTypeIdentifier.RECORD_TYPE_STEPS, StepsRecord.class); 229 mRecordIdToExternalRecordClassMap.put( 230 RecordTypeIdentifier.RECORD_TYPE_HEART_RATE, HeartRateRecord.class); 231 232 mRecordIdToExternalRecordClassMap.put( 233 RecordTypeIdentifier.RECORD_TYPE_HYDRATION, HydrationRecord.class); 234 mRecordIdToExternalRecordClassMap.put( 235 RecordTypeIdentifier.RECORD_TYPE_ACTIVE_CALORIES_BURNED, 236 ActiveCaloriesBurnedRecord.class); 237 mRecordIdToExternalRecordClassMap.put( 238 RecordTypeIdentifier.RECORD_TYPE_ELEVATION_GAINED, ElevationGainedRecord.class); 239 mRecordIdToExternalRecordClassMap.put( 240 RecordTypeIdentifier.RECORD_TYPE_DISTANCE, DistanceRecord.class); 241 mRecordIdToExternalRecordClassMap.put( 242 RecordTypeIdentifier.RECORD_TYPE_NUTRITION, NutritionRecord.class); 243 mRecordIdToExternalRecordClassMap.put( 244 RecordTypeIdentifier.RECORD_TYPE_FLOORS_CLIMBED, FloorsClimbedRecord.class); 245 mRecordIdToExternalRecordClassMap.put( 246 RecordTypeIdentifier.RECORD_TYPE_WHEELCHAIR_PUSHES, WheelchairPushesRecord.class); 247 mRecordIdToExternalRecordClassMap.put( 248 RecordTypeIdentifier.RECORD_TYPE_TOTAL_CALORIES_BURNED, 249 TotalCaloriesBurnedRecord.class); 250 251 mRecordIdToExternalRecordClassMap.put( 252 RecordTypeIdentifier.RECORD_TYPE_BASAL_METABOLIC_RATE, 253 BasalMetabolicRateRecord.class); 254 mRecordIdToExternalRecordClassMap.put( 255 RecordTypeIdentifier.RECORD_TYPE_CYCLING_PEDALING_CADENCE, 256 CyclingPedalingCadenceRecord.class); 257 mRecordIdToExternalRecordClassMap.put( 258 RecordTypeIdentifier.RECORD_TYPE_POWER, PowerRecord.class); 259 mRecordIdToExternalRecordClassMap.put( 260 RecordTypeIdentifier.RECORD_TYPE_SPEED, SpeedRecord.class); 261 mRecordIdToExternalRecordClassMap.put( 262 RecordTypeIdentifier.RECORD_TYPE_STEPS_CADENCE, StepsCadenceRecord.class); 263 264 mRecordIdToExternalRecordClassMap.put( 265 RecordTypeIdentifier.RECORD_TYPE_BODY_TEMPERATURE, BodyTemperatureRecord.class); 266 mRecordIdToExternalRecordClassMap.put( 267 RecordTypeIdentifier.RECORD_TYPE_BONE_MASS, BoneMassRecord.class); 268 mRecordIdToExternalRecordClassMap.put( 269 RecordTypeIdentifier.RECORD_TYPE_BLOOD_PRESSURE, BloodPressureRecord.class); 270 mRecordIdToExternalRecordClassMap.put( 271 RecordTypeIdentifier.RECORD_TYPE_BODY_FAT, BodyFatRecord.class); 272 mRecordIdToExternalRecordClassMap.put( 273 RecordTypeIdentifier.RECORD_TYPE_BLOOD_GLUCOSE, BloodGlucoseRecord.class); 274 mRecordIdToExternalRecordClassMap.put( 275 RecordTypeIdentifier.RECORD_TYPE_BASAL_BODY_TEMPERATURE, 276 BasalBodyTemperatureRecord.class); 277 mRecordIdToExternalRecordClassMap.put( 278 RecordTypeIdentifier.RECORD_TYPE_CERVICAL_MUCUS, CervicalMucusRecord.class); 279 mRecordIdToExternalRecordClassMap.put( 280 RecordTypeIdentifier.RECORD_TYPE_LEAN_BODY_MASS, LeanBodyMassRecord.class); 281 mRecordIdToExternalRecordClassMap.put( 282 RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_FLOW, MenstruationFlowRecord.class); 283 mRecordIdToExternalRecordClassMap.put( 284 RecordTypeIdentifier.RECORD_TYPE_HEIGHT, HeightRecord.class); 285 mRecordIdToExternalRecordClassMap.put( 286 RecordTypeIdentifier.RECORD_TYPE_OVULATION_TEST, OvulationTestRecord.class); 287 mRecordIdToExternalRecordClassMap.put( 288 RecordTypeIdentifier.RECORD_TYPE_VO2_MAX, Vo2MaxRecord.class); 289 mRecordIdToExternalRecordClassMap.put( 290 RecordTypeIdentifier.RECORD_TYPE_SEXUAL_ACTIVITY, SexualActivityRecord.class); 291 mRecordIdToExternalRecordClassMap.put( 292 RecordTypeIdentifier.RECORD_TYPE_SLEEP_SESSION, SleepSessionRecord.class); 293 mRecordIdToExternalRecordClassMap.put( 294 RecordTypeIdentifier.RECORD_TYPE_SKIN_TEMPERATURE, SkinTemperatureRecord.class); 295 296 mRecordIdToExternalRecordClassMap.put( 297 RecordTypeIdentifier.RECORD_TYPE_RESPIRATORY_RATE, RespiratoryRateRecord.class); 298 mRecordIdToExternalRecordClassMap.put( 299 RecordTypeIdentifier.RECORD_TYPE_OXYGEN_SATURATION, OxygenSaturationRecord.class); 300 mRecordIdToExternalRecordClassMap.put( 301 RecordTypeIdentifier.RECORD_TYPE_RESTING_HEART_RATE, RestingHeartRateRecord.class); 302 mRecordIdToExternalRecordClassMap.put( 303 RecordTypeIdentifier.RECORD_TYPE_WEIGHT, WeightRecord.class); 304 mRecordIdToExternalRecordClassMap.put( 305 RecordTypeIdentifier.RECORD_TYPE_BODY_WATER_MASS, BodyWaterMassRecord.class); 306 mRecordIdToExternalRecordClassMap.put( 307 RecordTypeIdentifier.RECORD_TYPE_HEART_RATE_VARIABILITY_RMSSD, 308 HeartRateVariabilityRmssdRecord.class); 309 mRecordIdToExternalRecordClassMap.put( 310 RecordTypeIdentifier.RECORD_TYPE_MENSTRUATION_PERIOD, 311 MenstruationPeriodRecord.class); 312 mRecordIdToExternalRecordClassMap.put( 313 RecordTypeIdentifier.RECORD_TYPE_INTERMENSTRUAL_BLEEDING, 314 IntermenstrualBleedingRecord.class); 315 mRecordIdToExternalRecordClassMap.put( 316 RecordTypeIdentifier.RECORD_TYPE_EXERCISE_SESSION, ExerciseSessionRecord.class); 317 mRecordIdToExternalRecordClassMap.put( 318 RecordTypeIdentifier.RECORD_TYPE_PLANNED_EXERCISE_SESSION, 319 PlannedExerciseSessionRecord.class); 320 321 mExternalRecordClassToRecordIdMap = 322 new ArrayMap<>(mRecordIdToExternalRecordClassMap.size()); 323 mRecordIdToExternalRecordClassMap.forEach( 324 (id, recordClass) -> mExternalRecordClassToRecordIdMap.put(recordClass, id)); 325 } 326 327 @NonNull getInstance()328 public static synchronized RecordMapper getInstance() { 329 if (sRecordMapper == null) { 330 sRecordMapper = new RecordMapper(); 331 } 332 333 return sRecordMapper; 334 } 335 336 @NonNull getRecordIdToInternalRecordClassMap()337 public Map<Integer, Class<? extends RecordInternal<?>>> getRecordIdToInternalRecordClassMap() { 338 return mRecordIdToInternalRecordClassMap; 339 } 340 341 @NonNull getRecordIdToExternalRecordClassMap()342 public Map<Integer, Class<? extends Record>> getRecordIdToExternalRecordClassMap() { 343 return mRecordIdToExternalRecordClassMap; 344 } 345 346 @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression 347 @RecordTypeIdentifier.RecordType getRecordType(Class<? extends Record> recordClass)348 public int getRecordType(Class<? extends Record> recordClass) { 349 return mExternalRecordClassToRecordIdMap.get(recordClass); 350 } 351 352 /** Checks whether the given {@code recordClass} can be mapped. */ hasRecordType(Class<? extends Record> recordClass)353 public boolean hasRecordType(Class<? extends Record> recordClass) { 354 return mExternalRecordClassToRecordIdMap.containsKey(recordClass); 355 } 356 } 357