• 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.BasalMetabolicRateRecord.BASAL_CALORIES_TOTAL;
21 import static android.health.connect.datatypes.DistanceRecord.DISTANCE_TOTAL;
22 import static android.health.connect.datatypes.ElevationGainedRecord.ELEVATION_GAINED_TOTAL;
23 import static android.health.connect.datatypes.ExerciseSessionRecord.EXERCISE_DURATION_TOTAL;
24 import static android.health.connect.datatypes.FloorsClimbedRecord.FLOORS_CLIMBED_TOTAL;
25 import static android.health.connect.datatypes.HeartRateRecord.BPM_AVG;
26 import static android.health.connect.datatypes.HeartRateRecord.BPM_MAX;
27 import static android.health.connect.datatypes.HeartRateRecord.BPM_MIN;
28 import static android.health.connect.datatypes.HeartRateRecord.HEART_MEASUREMENTS_COUNT;
29 import static android.health.connect.datatypes.HeightRecord.HEIGHT_AVG;
30 import static android.health.connect.datatypes.HeightRecord.HEIGHT_MAX;
31 import static android.health.connect.datatypes.HeightRecord.HEIGHT_MIN;
32 import static android.health.connect.datatypes.HydrationRecord.VOLUME_TOTAL;
33 import static android.health.connect.datatypes.NutritionRecord.BIOTIN_TOTAL;
34 import static android.health.connect.datatypes.NutritionRecord.CAFFEINE_TOTAL;
35 import static android.health.connect.datatypes.NutritionRecord.CALCIUM_TOTAL;
36 import static android.health.connect.datatypes.NutritionRecord.CHLORIDE_TOTAL;
37 import static android.health.connect.datatypes.NutritionRecord.CHOLESTEROL_TOTAL;
38 import static android.health.connect.datatypes.NutritionRecord.CHROMIUM_TOTAL;
39 import static android.health.connect.datatypes.NutritionRecord.COPPER_TOTAL;
40 import static android.health.connect.datatypes.NutritionRecord.DIETARY_FIBER_TOTAL;
41 import static android.health.connect.datatypes.NutritionRecord.ENERGY_FROM_FAT_TOTAL;
42 import static android.health.connect.datatypes.NutritionRecord.ENERGY_TOTAL;
43 import static android.health.connect.datatypes.NutritionRecord.FOLATE_TOTAL;
44 import static android.health.connect.datatypes.NutritionRecord.FOLIC_ACID_TOTAL;
45 import static android.health.connect.datatypes.NutritionRecord.IODINE_TOTAL;
46 import static android.health.connect.datatypes.NutritionRecord.IRON_TOTAL;
47 import static android.health.connect.datatypes.NutritionRecord.MAGNESIUM_TOTAL;
48 import static android.health.connect.datatypes.NutritionRecord.MANGANESE_TOTAL;
49 import static android.health.connect.datatypes.NutritionRecord.MOLYBDENUM_TOTAL;
50 import static android.health.connect.datatypes.NutritionRecord.MONOUNSATURATED_FAT_TOTAL;
51 import static android.health.connect.datatypes.NutritionRecord.NIACIN_TOTAL;
52 import static android.health.connect.datatypes.NutritionRecord.PANTOTHENIC_ACID_TOTAL;
53 import static android.health.connect.datatypes.NutritionRecord.PHOSPHORUS_TOTAL;
54 import static android.health.connect.datatypes.NutritionRecord.POLYUNSATURATED_FAT_TOTAL;
55 import static android.health.connect.datatypes.NutritionRecord.POTASSIUM_TOTAL;
56 import static android.health.connect.datatypes.NutritionRecord.PROTEIN_TOTAL;
57 import static android.health.connect.datatypes.NutritionRecord.RIBOFLAVIN_TOTAL;
58 import static android.health.connect.datatypes.NutritionRecord.SATURATED_FAT_TOTAL;
59 import static android.health.connect.datatypes.NutritionRecord.SELENIUM_TOTAL;
60 import static android.health.connect.datatypes.NutritionRecord.SODIUM_TOTAL;
61 import static android.health.connect.datatypes.NutritionRecord.SUGAR_TOTAL;
62 import static android.health.connect.datatypes.NutritionRecord.THIAMIN_TOTAL;
63 import static android.health.connect.datatypes.NutritionRecord.TOTAL_CARBOHYDRATE_TOTAL;
64 import static android.health.connect.datatypes.NutritionRecord.TOTAL_FAT_TOTAL;
65 import static android.health.connect.datatypes.NutritionRecord.UNSATURATED_FAT_TOTAL;
66 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_A_TOTAL;
67 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_B12_TOTAL;
68 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_B6_TOTAL;
69 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_C_TOTAL;
70 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_D_TOTAL;
71 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_E_TOTAL;
72 import static android.health.connect.datatypes.NutritionRecord.VITAMIN_K_TOTAL;
73 import static android.health.connect.datatypes.NutritionRecord.ZINC_TOTAL;
74 import static android.health.connect.datatypes.PowerRecord.POWER_AVG;
75 import static android.health.connect.datatypes.PowerRecord.POWER_MAX;
76 import static android.health.connect.datatypes.PowerRecord.POWER_MIN;
77 import static android.health.connect.datatypes.SleepSessionRecord.SLEEP_DURATION_TOTAL;
78 import static android.health.connect.datatypes.StepsRecord.STEPS_COUNT_TOTAL;
79 import static android.health.connect.datatypes.WeightRecord.WEIGHT_AVG;
80 import static android.health.connect.datatypes.WeightRecord.WEIGHT_MAX;
81 import static android.health.connect.datatypes.WeightRecord.WEIGHT_MIN;
82 import static android.health.connect.datatypes.WheelchairPushesRecord.WHEEL_CHAIR_PUSHES_COUNT_TOTAL;
83 
84 import android.annotation.NonNull;
85 import android.health.connect.AggregateResult;
86 import android.health.connect.datatypes.AggregationType;
87 import android.health.connect.datatypes.RestingHeartRateRecord;
88 import android.health.connect.datatypes.TotalCaloriesBurnedRecord;
89 import android.health.connect.datatypes.units.Energy;
90 import android.health.connect.datatypes.units.Length;
91 import android.health.connect.datatypes.units.Mass;
92 import android.health.connect.datatypes.units.Power;
93 import android.health.connect.datatypes.units.Volume;
94 import android.os.Parcel;
95 
96 import java.util.Arrays;
97 import java.util.HashMap;
98 import java.util.List;
99 import java.util.Map;
100 
101 /**
102  * Creates and maintains a map of {@link AggregationType.AggregationTypeIdentifier} to {@link
103  * AggregationType} and its result creator {@link AggregationResultCreator}
104  *
105  * @hide
106  */
107 public final class AggregationTypeIdMapper {
108     private static final int MAP_SIZE = 65;
109     private static volatile AggregationTypeIdMapper sAggregationTypeIdMapper;
110     private final Map<Integer, AggregationResultCreator> mIdToAggregateResult;
111     private final Map<Integer, AggregationType<?>> mIdDataAggregationTypeMap;
112     private final Map<AggregationType<?>, Integer> mDataAggregationTypeIdMap;
113 
AggregationTypeIdMapper()114     private AggregationTypeIdMapper() {
115         mIdToAggregateResult = new HashMap<>(MAP_SIZE);
116         mIdDataAggregationTypeMap = new HashMap<>(MAP_SIZE);
117         mDataAggregationTypeIdMap = new HashMap<>(MAP_SIZE);
118 
119         addLongIdsToAggregateResultMap(
120                 Arrays.asList(
121                         BPM_MAX,
122                         BPM_MIN,
123                         STEPS_COUNT_TOTAL,
124                         BPM_AVG,
125                         RestingHeartRateRecord.BPM_MAX,
126                         RestingHeartRateRecord.BPM_MIN,
127                         RestingHeartRateRecord.BPM_AVG,
128                         WHEEL_CHAIR_PUSHES_COUNT_TOTAL,
129                         HEART_MEASUREMENTS_COUNT,
130                         SLEEP_DURATION_TOTAL,
131                         EXERCISE_DURATION_TOTAL));
132         addDoubleIdsToAggregateResultMap(Arrays.asList(FLOORS_CLIMBED_TOTAL));
133         addPowerIdsToAggregateResultMap(Arrays.asList(POWER_MIN, POWER_MAX, POWER_AVG));
134         addEnergyIdsToAggregateResultMap(
135                 Arrays.asList(
136                         ACTIVE_CALORIES_TOTAL,
137                         BASAL_CALORIES_TOTAL,
138                         ENERGY_TOTAL,
139                         ENERGY_FROM_FAT_TOTAL,
140                         TotalCaloriesBurnedRecord.ENERGY_TOTAL));
141         addVolumeIdsToAggregateResultMap(Arrays.asList(VOLUME_TOTAL));
142         addLengthIdsToAggregateResultMap(
143                 Arrays.asList(
144                         DISTANCE_TOTAL,
145                         ELEVATION_GAINED_TOTAL,
146                         HEIGHT_AVG,
147                         HEIGHT_MAX,
148                         HEIGHT_MIN));
149         addMassIdsToAggregateResultMap(
150                 Arrays.asList(
151                         BIOTIN_TOTAL,
152                         CAFFEINE_TOTAL,
153                         CALCIUM_TOTAL,
154                         CHLORIDE_TOTAL,
155                         CHOLESTEROL_TOTAL,
156                         CHROMIUM_TOTAL,
157                         COPPER_TOTAL,
158                         DIETARY_FIBER_TOTAL,
159                         FOLATE_TOTAL,
160                         FOLIC_ACID_TOTAL,
161                         IODINE_TOTAL,
162                         IRON_TOTAL,
163                         MAGNESIUM_TOTAL,
164                         MANGANESE_TOTAL,
165                         MOLYBDENUM_TOTAL,
166                         MONOUNSATURATED_FAT_TOTAL,
167                         NIACIN_TOTAL,
168                         PANTOTHENIC_ACID_TOTAL,
169                         PHOSPHORUS_TOTAL,
170                         POLYUNSATURATED_FAT_TOTAL,
171                         POTASSIUM_TOTAL,
172                         PROTEIN_TOTAL,
173                         RIBOFLAVIN_TOTAL,
174                         SATURATED_FAT_TOTAL,
175                         SELENIUM_TOTAL,
176                         SODIUM_TOTAL,
177                         SUGAR_TOTAL,
178                         THIAMIN_TOTAL,
179                         TOTAL_CARBOHYDRATE_TOTAL,
180                         TOTAL_FAT_TOTAL,
181                         UNSATURATED_FAT_TOTAL,
182                         VITAMIN_A_TOTAL,
183                         VITAMIN_B12_TOTAL,
184                         VITAMIN_B6_TOTAL,
185                         VITAMIN_C_TOTAL,
186                         VITAMIN_D_TOTAL,
187                         VITAMIN_E_TOTAL,
188                         VITAMIN_K_TOTAL,
189                         ZINC_TOTAL,
190                         WEIGHT_AVG,
191                         WEIGHT_MAX,
192                         WEIGHT_MIN));
193     }
194 
195     @NonNull
getInstance()196     public static synchronized AggregationTypeIdMapper getInstance() {
197         if (sAggregationTypeIdMapper == null) {
198             sAggregationTypeIdMapper = new AggregationTypeIdMapper();
199         }
200 
201         return sAggregationTypeIdMapper;
202     }
203 
204     @NonNull
getAggregateResultFor( @ggregationType.AggregationTypeIdentifier.Id int id, @NonNull Parcel parcel)205     public AggregateResult<?> getAggregateResultFor(
206             @AggregationType.AggregationTypeIdentifier.Id int id, @NonNull Parcel parcel) {
207         return mIdToAggregateResult.get(id).getAggregateResult(parcel);
208     }
209 
210     @NonNull
getAggregationTypeFor( @ggregationType.AggregationTypeIdentifier.Id int id)211     public AggregationType<?> getAggregationTypeFor(
212             @AggregationType.AggregationTypeIdentifier.Id int id) {
213         return mIdDataAggregationTypeMap.get(id);
214     }
215 
216     @NonNull
217     @AggregationType.AggregationTypeIdentifier.Id
getIdFor(AggregationType<?> aggregationType)218     public int getIdFor(AggregationType<?> aggregationType) {
219         return mDataAggregationTypeIdMap.get(aggregationType);
220     }
221 
222     @NonNull
getLongResult(long result)223     private AggregateResult<Long> getLongResult(long result) {
224         return new AggregateResult<>(result);
225     }
226 
227     @NonNull
getDoubleResult(double result)228     private AggregateResult<Double> getDoubleResult(double result) {
229         return new AggregateResult<>(result);
230     }
231 
232     @NonNull
getEnergyResult(double result)233     private AggregateResult<Energy> getEnergyResult(double result) {
234         return new AggregateResult<>(Energy.fromCalories(result));
235     }
236 
237     @NonNull
getPowerResult(double result)238     private AggregateResult<Power> getPowerResult(double result) {
239         return new AggregateResult<>(Power.fromWatts(result));
240     }
241 
242     @NonNull
getLengthResult(double result)243     private AggregateResult<Length> getLengthResult(double result) {
244         return new AggregateResult<>(Length.fromMeters(result));
245     }
246 
247     @NonNull
getVolumeResult(double result)248     private AggregateResult<Volume> getVolumeResult(double result) {
249         return new AggregateResult<>(Volume.fromLiters(result));
250     }
251 
252     @NonNull
getMassResult(double result)253     private AggregateResult<Mass> getMassResult(double result) {
254         return new AggregateResult<>(Mass.fromGrams(result));
255     }
256 
addLongIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)257     private void addLongIdsToAggregateResultMap(
258             @NonNull List<AggregationType<?>> aggregationTypeList) {
259         for (AggregationType<?> aggregationType : aggregationTypeList) {
260             mIdToAggregateResult.put(
261                     aggregationType.getAggregationTypeIdentifier(),
262                     result -> getLongResult(result.readLong()));
263             populateIdDataAggregationType(aggregationType);
264         }
265     }
266 
addDoubleIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)267     private void addDoubleIdsToAggregateResultMap(
268             @NonNull List<AggregationType<?>> aggregationTypeList) {
269         for (AggregationType<?> aggregationType : aggregationTypeList) {
270             mIdToAggregateResult.put(
271                     aggregationType.getAggregationTypeIdentifier(),
272                     result -> getDoubleResult(result.readDouble()));
273             populateIdDataAggregationType(aggregationType);
274         }
275     }
276 
addEnergyIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)277     private void addEnergyIdsToAggregateResultMap(
278             @NonNull List<AggregationType<?>> aggregationTypeList) {
279         for (AggregationType<?> aggregationType : aggregationTypeList) {
280             mIdToAggregateResult.put(
281                     aggregationType.getAggregationTypeIdentifier(),
282                     result -> getEnergyResult(result.readDouble()));
283             populateIdDataAggregationType(aggregationType);
284         }
285     }
286 
addPowerIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)287     private void addPowerIdsToAggregateResultMap(
288             @NonNull List<AggregationType<?>> aggregationTypeList) {
289         for (AggregationType<?> aggregationType : aggregationTypeList) {
290             mIdToAggregateResult.put(
291                     aggregationType.getAggregationTypeIdentifier(),
292                     result -> getPowerResult(result.readDouble()));
293             populateIdDataAggregationType(aggregationType);
294         }
295     }
296 
addLengthIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)297     private void addLengthIdsToAggregateResultMap(
298             @NonNull List<AggregationType<?>> aggregationTypeList) {
299         for (AggregationType<?> aggregationType : aggregationTypeList) {
300             mIdToAggregateResult.put(
301                     aggregationType.getAggregationTypeIdentifier(),
302                     result -> getLengthResult(result.readDouble()));
303             populateIdDataAggregationType(aggregationType);
304         }
305     }
306 
addVolumeIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)307     private void addVolumeIdsToAggregateResultMap(
308             @NonNull List<AggregationType<?>> aggregationTypeList) {
309         for (AggregationType<?> aggregationType : aggregationTypeList) {
310             mIdToAggregateResult.put(
311                     aggregationType.getAggregationTypeIdentifier(),
312                     result -> getVolumeResult(result.readDouble()));
313             populateIdDataAggregationType(aggregationType);
314         }
315     }
316 
addMassIdsToAggregateResultMap( @onNull List<AggregationType<?>> aggregationTypeList)317     private void addMassIdsToAggregateResultMap(
318             @NonNull List<AggregationType<?>> aggregationTypeList) {
319         for (AggregationType<?> aggregationType : aggregationTypeList) {
320             mIdToAggregateResult.put(
321                     aggregationType.getAggregationTypeIdentifier(),
322                     result -> getMassResult(result.readDouble()));
323             populateIdDataAggregationType(aggregationType);
324         }
325     }
326 
populateIdDataAggregationType(AggregationType<?> aggregationType)327     private void populateIdDataAggregationType(AggregationType<?> aggregationType) {
328         mIdDataAggregationTypeMap.put(
329                 aggregationType.getAggregationTypeIdentifier(), aggregationType);
330         mDataAggregationTypeIdMap.put(
331                 aggregationType, aggregationType.getAggregationTypeIdentifier());
332     }
333 
334     /**
335      * Implementation should get and covert result to appropriate type (such as long, double etc.)
336      * using {@code result}
337      */
338     private interface AggregationResultCreator {
getAggregateResult(Parcel result)339         AggregateResult<?> getAggregateResult(Parcel result);
340     }
341 }
342