• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.health.connect.datatypes.ActiveCaloriesBurnedRecord.ACTIVE_CALORIES_TOTAL;
20 import static android.health.connect.datatypes.ActivityIntensityRecord.DURATION_TOTAL;
21 import static android.health.connect.datatypes.ActivityIntensityRecord.INTENSITY_MINUTES_TOTAL;
22 import static android.health.connect.datatypes.ActivityIntensityRecord.MODERATE_DURATION_TOTAL;
23 import static android.health.connect.datatypes.ActivityIntensityRecord.VIGOROUS_DURATION_TOTAL;
24 import static android.health.connect.datatypes.BasalMetabolicRateRecord.BASAL_CALORIES_TOTAL;
25 import static android.health.connect.datatypes.BloodPressureRecord.DIASTOLIC_AVG;
26 import static android.health.connect.datatypes.BloodPressureRecord.DIASTOLIC_MAX;
27 import static android.health.connect.datatypes.BloodPressureRecord.DIASTOLIC_MIN;
28 import static android.health.connect.datatypes.BloodPressureRecord.SYSTOLIC_AVG;
29 import static android.health.connect.datatypes.BloodPressureRecord.SYSTOLIC_MAX;
30 import static android.health.connect.datatypes.BloodPressureRecord.SYSTOLIC_MIN;
31 import static android.health.connect.datatypes.CyclingPedalingCadenceRecord.RPM_AVG;
32 import static android.health.connect.datatypes.CyclingPedalingCadenceRecord.RPM_MAX;
33 import static android.health.connect.datatypes.CyclingPedalingCadenceRecord.RPM_MIN;
34 import static android.health.connect.datatypes.DistanceRecord.DISTANCE_TOTAL;
35 import static android.health.connect.datatypes.ElevationGainedRecord.ELEVATION_GAINED_TOTAL;
36 import static android.health.connect.datatypes.ExerciseSessionRecord.EXERCISE_DURATION_TOTAL;
37 import static android.health.connect.datatypes.FloorsClimbedRecord.FLOORS_CLIMBED_TOTAL;
38 import static android.health.connect.datatypes.HeartRateRecord.BPM_AVG;
39 import static android.health.connect.datatypes.HeartRateRecord.BPM_MAX;
40 import static android.health.connect.datatypes.HeartRateRecord.BPM_MIN;
41 import static android.health.connect.datatypes.HeartRateRecord.HEART_MEASUREMENTS_COUNT;
42 import static android.health.connect.datatypes.HeightRecord.HEIGHT_AVG;
43 import static android.health.connect.datatypes.HeightRecord.HEIGHT_MAX;
44 import static android.health.connect.datatypes.HeightRecord.HEIGHT_MIN;
45 import static android.health.connect.datatypes.HydrationRecord.VOLUME_TOTAL;
46 import static android.health.connect.datatypes.MindfulnessSessionRecord.MINDFULNESS_DURATION_TOTAL;
47 import static android.health.connect.datatypes.NutritionRecord.BIOTIN_TOTAL;
48 import static android.health.connect.datatypes.NutritionRecord.CAFFEINE_TOTAL;
49 import static android.health.connect.datatypes.NutritionRecord.CALCIUM_TOTAL;
50 import static android.health.connect.datatypes.NutritionRecord.CHLORIDE_TOTAL;
51 import static android.health.connect.datatypes.NutritionRecord.CHOLESTEROL_TOTAL;
52 import static android.health.connect.datatypes.NutritionRecord.CHROMIUM_TOTAL;
53 import static android.health.connect.datatypes.NutritionRecord.COPPER_TOTAL;
54 import static android.health.connect.datatypes.NutritionRecord.DIETARY_FIBER_TOTAL;
55 import static android.health.connect.datatypes.NutritionRecord.ENERGY_FROM_FAT_TOTAL;
56 import static android.health.connect.datatypes.NutritionRecord.ENERGY_TOTAL;
57 import static android.health.connect.datatypes.NutritionRecord.FOLATE_TOTAL;
58 import static android.health.connect.datatypes.NutritionRecord.FOLIC_ACID_TOTAL;
59 import static android.health.connect.datatypes.NutritionRecord.IODINE_TOTAL;
60 import static android.health.connect.datatypes.NutritionRecord.IRON_TOTAL;
61 import static android.health.connect.datatypes.NutritionRecord.MAGNESIUM_TOTAL;
62 import static android.health.connect.datatypes.NutritionRecord.MANGANESE_TOTAL;
63 import static android.health.connect.datatypes.NutritionRecord.MOLYBDENUM_TOTAL;
64 import static android.health.connect.datatypes.NutritionRecord.MONOUNSATURATED_FAT_TOTAL;
65 import static android.health.connect.datatypes.NutritionRecord.NIACIN_TOTAL;
66 import static android.health.connect.datatypes.NutritionRecord.PANTOTHENIC_ACID_TOTAL;
67 import static android.health.connect.datatypes.NutritionRecord.PHOSPHORUS_TOTAL;
68 import static android.health.connect.datatypes.NutritionRecord.POLYUNSATURATED_FAT_TOTAL;
69 import static android.health.connect.datatypes.NutritionRecord.POTASSIUM_TOTAL;
70 import static android.health.connect.datatypes.NutritionRecord.PROTEIN_TOTAL;
71 import static android.health.connect.datatypes.NutritionRecord.RIBOFLAVIN_TOTAL;
72 import static android.health.connect.datatypes.NutritionRecord.SATURATED_FAT_TOTAL;
73 import static android.health.connect.datatypes.NutritionRecord.SELENIUM_TOTAL;
74 import static android.health.connect.datatypes.NutritionRecord.SODIUM_TOTAL;
75 import static android.health.connect.datatypes.NutritionRecord.SUGAR_TOTAL;
76 import static android.health.connect.datatypes.NutritionRecord.THIAMIN_TOTAL;
77 import static android.health.connect.datatypes.NutritionRecord.TOTAL_CARBOHYDRATE_TOTAL;
78 import static android.health.connect.datatypes.NutritionRecord.TOTAL_FAT_TOTAL;
79 import static android.health.connect.datatypes.NutritionRecord.TRANS_FAT_TOTAL;
80 import static android.health.connect.datatypes.NutritionRecord.UNSATURATED_FAT_TOTAL;
81 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_A_TOTAL;
82 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_B12_TOTAL;
83 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_B6_TOTAL;
84 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_C_TOTAL;
85 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_D_TOTAL;
86 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_E_TOTAL;
87 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_K_TOTAL;
88 import static android.health.connect.datatypes.NutritionRecord.ZINC_TOTAL;
89 import static android.health.connect.datatypes.PowerRecord.POWER_AVG;
90 import static android.health.connect.datatypes.PowerRecord.POWER_MAX;
91 import static android.health.connect.datatypes.PowerRecord.POWER_MIN;
92 import static android.health.connect.datatypes.SkinTemperatureRecord.SKIN_TEMPERATURE_DELTA_AVG;
93 import static android.health.connect.datatypes.SkinTemperatureRecord.SKIN_TEMPERATURE_DELTA_MAX;
94 import static android.health.connect.datatypes.SkinTemperatureRecord.SKIN_TEMPERATURE_DELTA_MIN;
95 import static android.health.connect.datatypes.SleepSessionRecord.SLEEP_DURATION_TOTAL;
96 import static android.health.connect.datatypes.SpeedRecord.SPEED_AVG;
97 import static android.health.connect.datatypes.SpeedRecord.SPEED_MAX;
98 import static android.health.connect.datatypes.SpeedRecord.SPEED_MIN;
99 import static android.health.connect.datatypes.StepsCadenceRecord.STEPS_CADENCE_RATE_AVG;
100 import static android.health.connect.datatypes.StepsCadenceRecord.STEPS_CADENCE_RATE_MAX;
101 import static android.health.connect.datatypes.StepsCadenceRecord.STEPS_CADENCE_RATE_MIN;
102 import static android.health.connect.datatypes.StepsRecord.STEPS_COUNT_TOTAL;
103 import static android.health.connect.datatypes.WeightRecord.WEIGHT_AVG;
104 import static android.health.connect.datatypes.WeightRecord.WEIGHT_MAX;
105 import static android.health.connect.datatypes.WeightRecord.WEIGHT_MIN;
106 import static android.health.connect.datatypes.WheelchairPushesRecord.WHEEL_CHAIR_PUSHES_COUNT_TOTAL;
107 
108 import android.annotation.NonNull;
109 import android.health.connect.AggregateResult;
110 import android.health.connect.datatypes.AggregationType;
111 import android.health.connect.datatypes.RestingHeartRateRecord;
112 import android.health.connect.datatypes.TotalCaloriesBurnedRecord;
113 import android.health.connect.datatypes.units.Energy;
114 import android.health.connect.datatypes.units.Length;
115 import android.health.connect.datatypes.units.Mass;
116 import android.health.connect.datatypes.units.Power;
117 import android.health.connect.datatypes.units.Pressure;
118 import android.health.connect.datatypes.units.TemperatureDelta;
119 import android.health.connect.datatypes.units.Velocity;
120 import android.health.connect.datatypes.units.Volume;
121 import android.os.Parcel;
122 
123 import com.android.healthfitness.flags.AconfigFlagHelper;
124 import com.android.healthfitness.flags.Flags;
125 
126 import java.time.Duration;
127 import java.util.ArrayList;
128 import java.util.Arrays;
129 import java.util.HashMap;
130 import java.util.List;
131 import java.util.Map;
132 
133 /**
134  * Creates and maintains a map of {@link AggregationType.AggregationTypeIdentifier} to {@link
135  * AggregationType} and its result creator {@link AggregationResultCreator}
136  *
137  * @hide
138  */
139 public final class AggregationTypeIdMapper {
140     @SuppressWarnings("NullAway.Init") // TODO(b/317029272): fix this suppression
141     private static volatile AggregationTypeIdMapper sAggregationTypeIdMapper;
142 
143     private final Map<Integer, AggregationResultCreator> mIdToAggregateResult;
144     private final Map<Integer, AggregationType<?>> mIdDataAggregationTypeMap;
145     private final Map<AggregationType<?>, Integer> mDataAggregationTypeIdMap;
146 
AggregationTypeIdMapper()147     private AggregationTypeIdMapper() {
148         mIdToAggregateResult = new HashMap<>();
149         mIdDataAggregationTypeMap = new HashMap<>();
150         mDataAggregationTypeIdMap = new HashMap<>();
151 
152         List<AggregationType<?>> longAggregations =
153                 new ArrayList<>(
154                         List.of(
155                                 BPM_MAX,
156                                 BPM_MIN,
157                                 STEPS_COUNT_TOTAL,
158                                 BPM_AVG,
159                                 RestingHeartRateRecord.BPM_MAX,
160                                 RestingHeartRateRecord.BPM_MIN,
161                                 RestingHeartRateRecord.BPM_AVG,
162                                 WHEEL_CHAIR_PUSHES_COUNT_TOTAL,
163                                 HEART_MEASUREMENTS_COUNT,
164                                 SLEEP_DURATION_TOTAL,
165                                 EXERCISE_DURATION_TOTAL,
166                                 MINDFULNESS_DURATION_TOTAL));
167         List<AggregationType<?>> durationAggregations = new ArrayList<>();
168 
169         // Redundantly explicitly checking the flag to satisfy the linter.
170         if (Flags.activityIntensity() && AconfigFlagHelper.isActivityIntensityEnabled()) {
171             durationAggregations.add(MODERATE_DURATION_TOTAL);
172             durationAggregations.add(VIGOROUS_DURATION_TOTAL);
173             durationAggregations.add(DURATION_TOTAL);
174             longAggregations.add(INTENSITY_MINUTES_TOTAL);
175         }
176 
177         addLongIdsToAggregateResultMap(longAggregations);
178         addDoubleIdsToAggregateResultMap(
179                 Arrays.asList(
180                         FLOORS_CLIMBED_TOTAL,
181                         RPM_AVG,
182                         RPM_MAX,
183                         RPM_MIN,
184                         STEPS_CADENCE_RATE_MAX,
185                         STEPS_CADENCE_RATE_AVG,
186                         STEPS_CADENCE_RATE_MIN));
187         addPowerIdsToAggregateResultMap(Arrays.asList(POWER_MIN, POWER_MAX, POWER_AVG));
188         addTemperatureDeltaIdsToAggregateResultMap(
189                 Arrays.asList(
190                         SKIN_TEMPERATURE_DELTA_AVG,
191                         SKIN_TEMPERATURE_DELTA_MIN,
192                         SKIN_TEMPERATURE_DELTA_MAX));
193         addEnergyIdsToAggregateResultMap(
194                 Arrays.asList(
195                         ACTIVE_CALORIES_TOTAL,
196                         BASAL_CALORIES_TOTAL,
197                         ENERGY_TOTAL,
198                         ENERGY_FROM_FAT_TOTAL,
199                         TotalCaloriesBurnedRecord.ENERGY_TOTAL));
200         addVolumeIdsToAggregateResultMap(Arrays.asList(VOLUME_TOTAL));
201         addLengthIdsToAggregateResultMap(
202                 Arrays.asList(
203                         DISTANCE_TOTAL,
204                         ELEVATION_GAINED_TOTAL,
205                         HEIGHT_AVG,
206                         HEIGHT_MAX,
207                         HEIGHT_MIN));
208         addMassIdsToAggregateResultMap(
209                 Arrays.asList(
210                         BIOTIN_TOTAL,
211                         CAFFEINE_TOTAL,
212                         CALCIUM_TOTAL,
213                         CHLORIDE_TOTAL,
214                         CHOLESTEROL_TOTAL,
215                         CHROMIUM_TOTAL,
216                         COPPER_TOTAL,
217                         DIETARY_FIBER_TOTAL,
218                         FOLATE_TOTAL,
219                         FOLIC_ACID_TOTAL,
220                         IODINE_TOTAL,
221                         IRON_TOTAL,
222                         MAGNESIUM_TOTAL,
223                         MANGANESE_TOTAL,
224                         MOLYBDENUM_TOTAL,
225                         MONOUNSATURATED_FAT_TOTAL,
226                         NIACIN_TOTAL,
227                         PANTOTHENIC_ACID_TOTAL,
228                         PHOSPHORUS_TOTAL,
229                         POLYUNSATURATED_FAT_TOTAL,
230                         POTASSIUM_TOTAL,
231                         PROTEIN_TOTAL,
232                         RIBOFLAVIN_TOTAL,
233                         SATURATED_FAT_TOTAL,
234                         SELENIUM_TOTAL,
235                         SODIUM_TOTAL,
236                         SUGAR_TOTAL,
237                         THIAMIN_TOTAL,
238                         TOTAL_CARBOHYDRATE_TOTAL,
239                         TOTAL_FAT_TOTAL,
240                         UNSATURATED_FAT_TOTAL,
241                         VITAMIN_A_TOTAL,
242                         VITAMIN_B12_TOTAL,
243                         VITAMIN_B6_TOTAL,
244                         VITAMIN_C_TOTAL,
245                         VITAMIN_D_TOTAL,
246                         VITAMIN_E_TOTAL,
247                         VITAMIN_K_TOTAL,
248                         ZINC_TOTAL,
249                         WEIGHT_AVG,
250                         WEIGHT_MAX,
251                         WEIGHT_MIN,
252                         TRANS_FAT_TOTAL));
253         addVelocityIdsToAggregateResultMap(Arrays.asList(SPEED_MAX, SPEED_AVG, SPEED_MIN));
254         addPressureIdsToAggregateResultMap(
255                 Arrays.asList(
256                         DIASTOLIC_AVG,
257                         DIASTOLIC_MAX,
258                         DIASTOLIC_MIN,
259                         SYSTOLIC_AVG,
260                         SYSTOLIC_MAX,
261                         SYSTOLIC_MIN));
262         addDurationIdsToAggregateResultMap(durationAggregations);
263     }
264 
265     @NonNull
getInstance()266     public static synchronized AggregationTypeIdMapper getInstance() {
267         if (sAggregationTypeIdMapper == null) {
268             sAggregationTypeIdMapper = new AggregationTypeIdMapper();
269         }
270 
271         return sAggregationTypeIdMapper;
272     }
273 
274     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
275     @NonNull
getAggregateResultFor( @ggregationType.AggregationTypeIdentifier.Id int id, @NonNull Parcel parcel)276     public AggregateResult<?> getAggregateResultFor(
277             @AggregationType.AggregationTypeIdentifier.Id int id, @NonNull Parcel parcel) {
278         return mIdToAggregateResult.get(id).getAggregateResult(parcel);
279     }
280 
281     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
282     @NonNull
getAggregationTypeFor( @ggregationType.AggregationTypeIdentifier.Id int id)283     public AggregationType<?> getAggregationTypeFor(
284             @AggregationType.AggregationTypeIdentifier.Id int id) {
285         return mIdDataAggregationTypeMap.get(id);
286     }
287 
288     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
289     @NonNull
290     @AggregationType.AggregationTypeIdentifier.Id
getIdFor(AggregationType<?> aggregationType)291     public int getIdFor(AggregationType<?> aggregationType) {
292         return mDataAggregationTypeIdMap.get(aggregationType);
293     }
294 
295     @NonNull
getLongResult(long result)296     private AggregateResult<Long> getLongResult(long result) {
297         return new AggregateResult<>(result);
298     }
299 
300     @NonNull
getDoubleResult(double result)301     private AggregateResult<Double> getDoubleResult(double result) {
302         return new AggregateResult<>(result);
303     }
304 
305     @NonNull
getEnergyResult(double result)306     private AggregateResult<Energy> getEnergyResult(double result) {
307         return new AggregateResult<>(Energy.fromCalories(result));
308     }
309 
310     @NonNull
getPowerResult(double result)311     private AggregateResult<Power> getPowerResult(double result) {
312         return new AggregateResult<>(Power.fromWatts(result));
313     }
314 
315     @NonNull
getTemperatureDeltaResult(double result)316     private AggregateResult<TemperatureDelta> getTemperatureDeltaResult(double result) {
317         return new AggregateResult<>(TemperatureDelta.fromCelsius(result));
318     }
319 
320     @NonNull
getPressureResult(double result)321     private AggregateResult<Pressure> getPressureResult(double result) {
322         return new AggregateResult<>(Pressure.fromMillimetersOfMercury(result));
323     }
324 
325     @NonNull
getLengthResult(double result)326     private AggregateResult<Length> getLengthResult(double result) {
327         return new AggregateResult<>(Length.fromMeters(result));
328     }
329 
330     @NonNull
getVolumeResult(double result)331     private AggregateResult<Volume> getVolumeResult(double result) {
332         return new AggregateResult<>(Volume.fromLiters(result));
333     }
334 
335     @NonNull
getMassResult(double result)336     private AggregateResult<Mass> getMassResult(double result) {
337         return new AggregateResult<>(Mass.fromGrams(result));
338     }
339 
340     @NonNull
getVelocityResult(double result)341     private AggregateResult<Velocity> getVelocityResult(double result) {
342         return new AggregateResult<>(Velocity.fromMetersPerSecond(result));
343     }
344 
345     @NonNull
getDurationResult(long resultMillis)346     private AggregateResult<Duration> getDurationResult(long resultMillis) {
347         return new AggregateResult<>(Duration.ofMillis(resultMillis));
348     }
349 
addLongIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)350     private void addLongIdsToAggregateResultMap(
351             @NonNull List<AggregationType<?>> aggregationTypeList) {
352         for (AggregationType<?> aggregationType : aggregationTypeList) {
353             mIdToAggregateResult.put(
354                     aggregationType.getAggregationTypeIdentifier(),
355                     result -> getLongResult(result.readLong()));
356             populateIdDataAggregationType(aggregationType);
357         }
358     }
359 
addDoubleIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)360     private void addDoubleIdsToAggregateResultMap(
361             @NonNull List<AggregationType<?>> aggregationTypeList) {
362         for (AggregationType<?> aggregationType : aggregationTypeList) {
363             mIdToAggregateResult.put(
364                     aggregationType.getAggregationTypeIdentifier(),
365                     result -> getDoubleResult(result.readDouble()));
366             populateIdDataAggregationType(aggregationType);
367         }
368     }
369 
addEnergyIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)370     private void addEnergyIdsToAggregateResultMap(
371             @NonNull List<AggregationType<?>> aggregationTypeList) {
372         for (AggregationType<?> aggregationType : aggregationTypeList) {
373             mIdToAggregateResult.put(
374                     aggregationType.getAggregationTypeIdentifier(),
375                     result -> getEnergyResult(result.readDouble()));
376             populateIdDataAggregationType(aggregationType);
377         }
378     }
379 
addPowerIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)380     private void addPowerIdsToAggregateResultMap(
381             @NonNull List<AggregationType<?>> aggregationTypeList) {
382         for (AggregationType<?> aggregationType : aggregationTypeList) {
383             mIdToAggregateResult.put(
384                     aggregationType.getAggregationTypeIdentifier(),
385                     result -> getPowerResult(result.readDouble()));
386             populateIdDataAggregationType(aggregationType);
387         }
388     }
389 
addTemperatureDeltaIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)390     private void addTemperatureDeltaIdsToAggregateResultMap(
391             @NonNull List<AggregationType<?>> aggregationTypeList) {
392         for (AggregationType<?> aggregationType : aggregationTypeList) {
393             mIdToAggregateResult.put(
394                     aggregationType.getAggregationTypeIdentifier(),
395                     result -> getTemperatureDeltaResult(result.readDouble()));
396             populateIdDataAggregationType(aggregationType);
397         }
398     }
399 
addPressureIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)400     private void addPressureIdsToAggregateResultMap(
401             @NonNull List<AggregationType<?>> aggregationTypeList) {
402         for (AggregationType<?> aggregationType : aggregationTypeList) {
403             mIdToAggregateResult.put(
404                     aggregationType.getAggregationTypeIdentifier(),
405                     result -> getPressureResult(result.readDouble()));
406             populateIdDataAggregationType(aggregationType);
407         }
408     }
409 
addLengthIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)410     private void addLengthIdsToAggregateResultMap(
411             @NonNull List<AggregationType<?>> aggregationTypeList) {
412         for (AggregationType<?> aggregationType : aggregationTypeList) {
413             mIdToAggregateResult.put(
414                     aggregationType.getAggregationTypeIdentifier(),
415                     result -> getLengthResult(result.readDouble()));
416             populateIdDataAggregationType(aggregationType);
417         }
418     }
419 
addVolumeIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)420     private void addVolumeIdsToAggregateResultMap(
421             @NonNull List<AggregationType<?>> aggregationTypeList) {
422         for (AggregationType<?> aggregationType : aggregationTypeList) {
423             mIdToAggregateResult.put(
424                     aggregationType.getAggregationTypeIdentifier(),
425                     result -> getVolumeResult(result.readDouble()));
426             populateIdDataAggregationType(aggregationType);
427         }
428     }
429 
addMassIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)430     private void addMassIdsToAggregateResultMap(
431             @NonNull List<AggregationType<?>> aggregationTypeList) {
432         for (AggregationType<?> aggregationType : aggregationTypeList) {
433             mIdToAggregateResult.put(
434                     aggregationType.getAggregationTypeIdentifier(),
435                     result -> getMassResult(result.readDouble()));
436             populateIdDataAggregationType(aggregationType);
437         }
438     }
439 
addVelocityIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)440     private void addVelocityIdsToAggregateResultMap(
441             @NonNull List<AggregationType<?>> aggregationTypeList) {
442         for (AggregationType<?> aggregationType : aggregationTypeList) {
443             mIdToAggregateResult.put(
444                     aggregationType.getAggregationTypeIdentifier(),
445                     result -> getVelocityResult(result.readDouble()));
446             populateIdDataAggregationType(aggregationType);
447         }
448     }
449 
addDurationIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)450     private void addDurationIdsToAggregateResultMap(
451             @NonNull List<AggregationType<?>> aggregationTypeList) {
452         for (AggregationType<?> aggregationType : aggregationTypeList) {
453             mIdToAggregateResult.put(
454                     aggregationType.getAggregationTypeIdentifier(),
455                     result -> getDurationResult(result.readLong()));
456             populateIdDataAggregationType(aggregationType);
457         }
458     }
459 
populateIdDataAggregationType(AggregationType<?> aggregationType)460     private void populateIdDataAggregationType(AggregationType<?> aggregationType) {
461         mIdDataAggregationTypeMap.put(
462                 aggregationType.getAggregationTypeIdentifier(), aggregationType);
463         mDataAggregationTypeIdMap.put(
464                 aggregationType, aggregationType.getAggregationTypeIdentifier());
465     }
466 
467     /**
468      * Implementation should get and covert result to appropriate type (such as long, double etc.)
469      * using {@code result}
470      */
471     private interface AggregationResultCreator {
getAggregateResult(Parcel result)472         AggregateResult<?> getAggregateResult(Parcel result);
473     }
474 }
475