1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * ```
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  * ```
10  *
11  * Unless required by applicable law or agreed to in writing, software distributed under the License
12  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.android.healthconnect.testapps.toolbox
17 
18 import android.health.connect.datatypes.ActiveCaloriesBurnedRecord
19 import android.health.connect.datatypes.ActivityIntensityRecord
20 import android.health.connect.datatypes.BasalBodyTemperatureRecord
21 import android.health.connect.datatypes.BasalMetabolicRateRecord
22 import android.health.connect.datatypes.BloodGlucoseRecord
23 import android.health.connect.datatypes.BloodPressureRecord
24 import android.health.connect.datatypes.BodyFatRecord
25 import android.health.connect.datatypes.BodyTemperatureRecord
26 import android.health.connect.datatypes.BodyWaterMassRecord
27 import android.health.connect.datatypes.BoneMassRecord
28 import android.health.connect.datatypes.CervicalMucusRecord
29 import android.health.connect.datatypes.CyclingPedalingCadenceRecord
30 import android.health.connect.datatypes.DistanceRecord
31 import android.health.connect.datatypes.ElevationGainedRecord
32 import android.health.connect.datatypes.ExerciseSessionRecord
33 import android.health.connect.datatypes.FloorsClimbedRecord
34 import android.health.connect.datatypes.HeartRateRecord
35 import android.health.connect.datatypes.HeartRateVariabilityRmssdRecord
36 import android.health.connect.datatypes.HeightRecord
37 import android.health.connect.datatypes.HydrationRecord
38 import android.health.connect.datatypes.IntermenstrualBleedingRecord
39 import android.health.connect.datatypes.LeanBodyMassRecord
40 import android.health.connect.datatypes.MenstruationFlowRecord
41 import android.health.connect.datatypes.MenstruationPeriodRecord
42 import android.health.connect.datatypes.MindfulnessSessionRecord
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.RespiratoryRateRecord
50 import android.health.connect.datatypes.RestingHeartRateRecord
51 import android.health.connect.datatypes.SexualActivityRecord
52 import android.health.connect.datatypes.SkinTemperatureRecord
53 import android.health.connect.datatypes.SleepSessionRecord
54 import android.health.connect.datatypes.SpeedRecord
55 import android.health.connect.datatypes.StepsCadenceRecord
56 import android.health.connect.datatypes.StepsRecord
57 import android.health.connect.datatypes.TotalCaloriesBurnedRecord
58 import android.health.connect.datatypes.Vo2MaxRecord
59 import android.health.connect.datatypes.WeightRecord
60 import android.health.connect.datatypes.WheelchairPushesRecord
61 import android.text.InputType
62 import androidx.annotation.DrawableRes
63 import androidx.annotation.StringRes
64 import kotlin.reflect.KClass
65 
66 /** Constant variables used across the app. */
67 object Constants {
68 
69     const val INPUT_TYPE_DOUBLE = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
70     const val INPUT_TYPE_SIGNED_DOUBLE =
71         InputType.TYPE_CLASS_NUMBER or
72             InputType.TYPE_NUMBER_FLAG_DECIMAL or
73             InputType.TYPE_NUMBER_FLAG_SIGNED
74     const val INPUT_TYPE_LONG = InputType.TYPE_CLASS_NUMBER
75     const val INPUT_TYPE_INT = InputType.TYPE_CLASS_NUMBER
76     const val INPUT_TYPE_TEXT = InputType.TYPE_CLASS_TEXT
77 
78     val FITNESS_READ_PERMISSIONS =
79         arrayOf(
80             "android.permission.health.READ_ACTIVE_CALORIES_BURNED",
81             "android.permission.health.READ_ACTIVITY_INTENSITY",
82             "android.permission.health.READ_BASAL_BODY_TEMPERATURE",
83             "android.permission.health.READ_BASAL_METABOLIC_RATE",
84             "android.permission.health.READ_BLOOD_GLUCOSE",
85             "android.permission.health.READ_BLOOD_PRESSURE",
86             "android.permission.health.READ_BODY_FAT",
87             "android.permission.health.READ_BODY_TEMPERATURE",
88             "android.permission.health.READ_BODY_WATER_MASS",
89             "android.permission.health.READ_BONE_MASS",
90             "android.permission.health.READ_CERVICAL_MUCUS",
91             "android.permission.health.READ_DISTANCE",
92             "android.permission.health.READ_ELEVATION_GAINED",
93             "android.permission.health.READ_EXERCISE",
94             "android.permission.health.READ_PLANNED_EXERCISE",
95             "android.permission.health.READ_EXERCISE_ROUTES",
96             "android.permission.health.READ_FLOORS_CLIMBED",
97             "android.permission.health.READ_HEART_RATE",
98             "android.permission.health.READ_HEART_RATE_VARIABILITY",
99             "android.permission.health.READ_HEIGHT",
100             "android.permission.health.READ_HYDRATION",
101             "android.permission.health.READ_LEAN_BODY_MASS",
102             "android.permission.health.READ_MENSTRUATION",
103             "android.permission.health.READ_MINDFULNESS",
104             "android.permission.health.READ_NUTRITION",
105             "android.permission.health.READ_OVULATION_TEST",
106             "android.permission.health.READ_OXYGEN_SATURATION",
107             "android.permission.health.READ_POWER",
108             "android.permission.health.READ_RESPIRATORY_RATE",
109             "android.permission.health.READ_RESTING_HEART_RATE",
110             "android.permission.health.READ_SEXUAL_ACTIVITY",
111             "android.permission.health.READ_SKIN_TEMPERATURE",
112             "android.permission.health.READ_SLEEP",
113             "android.permission.health.READ_SPEED",
114             "android.permission.health.READ_STEPS",
115             "android.permission.health.READ_TOTAL_CALORIES_BURNED",
116             "android.permission.health.READ_VO2_MAX",
117             "android.permission.health.READ_WEIGHT",
118             "android.permission.health.READ_INTERMENSTRUAL_BLEEDING",
119             "android.permission.health.READ_WHEELCHAIR_PUSHES",
120         )
121 
122     val FITNESS_WRITE_PERMISSIONS =
123         arrayOf(
124             "android.permission.health.WRITE_ACTIVE_CALORIES_BURNED",
125             "android.permission.health.WRITE_ACTIVITY_INTENSITY",
126             "android.permission.health.WRITE_BASAL_BODY_TEMPERATURE",
127             "android.permission.health.WRITE_BASAL_METABOLIC_RATE",
128             "android.permission.health.WRITE_BLOOD_GLUCOSE",
129             "android.permission.health.WRITE_BLOOD_PRESSURE",
130             "android.permission.health.WRITE_BODY_FAT",
131             "android.permission.health.WRITE_BODY_TEMPERATURE",
132             "android.permission.health.WRITE_BODY_WATER_MASS",
133             "android.permission.health.WRITE_BONE_MASS",
134             "android.permission.health.WRITE_CERVICAL_MUCUS",
135             "android.permission.health.WRITE_DISTANCE",
136             "android.permission.health.WRITE_ELEVATION_GAINED",
137             "android.permission.health.WRITE_EXERCISE",
138             "android.permission.health.WRITE_PLANNED_EXERCISE",
139             "android.permission.health.WRITE_FLOORS_CLIMBED",
140             "android.permission.health.WRITE_HEART_RATE",
141             "android.permission.health.WRITE_HEART_RATE_VARIABILITY",
142             "android.permission.health.WRITE_HEIGHT",
143             "android.permission.health.WRITE_HYDRATION",
144             "android.permission.health.WRITE_LEAN_BODY_MASS",
145             "android.permission.health.WRITE_MENSTRUATION",
146             "android.permission.health.WRITE_MINDFULNESS",
147             "android.permission.health.WRITE_NUTRITION",
148             "android.permission.health.WRITE_OVULATION_TEST",
149             "android.permission.health.WRITE_OXYGEN_SATURATION",
150             "android.permission.health.WRITE_POWER",
151             "android.permission.health.WRITE_RESPIRATORY_RATE",
152             "android.permission.health.WRITE_RESTING_HEART_RATE",
153             "android.permission.health.WRITE_SEXUAL_ACTIVITY",
154             "android.permission.health.WRITE_SKIN_TEMPERATURE",
155             "android.permission.health.WRITE_SLEEP",
156             "android.permission.health.WRITE_SPEED",
157             "android.permission.health.WRITE_STEPS",
158             "android.permission.health.WRITE_TOTAL_CALORIES_BURNED",
159             "android.permission.health.WRITE_VO2_MAX",
160             "android.permission.health.WRITE_WEIGHT",
161             "android.permission.health.WRITE_WHEELCHAIR_PUSHES",
162             "android.permission.health.WRITE_INTERMENSTRUAL_BLEEDING",
163             "android.permission.health.WRITE_EXERCISE_ROUTE",
164         )
165     val FITNESS_PERMISSIONS = FITNESS_READ_PERMISSIONS + FITNESS_WRITE_PERMISSIONS
166 
167     const val READ_HEALTH_DATA_IN_BACKGROUND =
168         "android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND"
169     const val READ_HEALTH_DATA_HISTORY = "android.permission.health.READ_HEALTH_DATA_HISTORY"
170 
171     val ADDITIONAL_PERMISSIONS = arrayOf(READ_HEALTH_DATA_IN_BACKGROUND, READ_HEALTH_DATA_HISTORY)
172 
173     const val READ_IMMUNIZATION = "android.permission.health.READ_MEDICAL_DATA_VACCINES"
174     const val WRITE_ALL_MEDICAL_DATA = "android.permission.health.WRITE_MEDICAL_DATA"
175     val MEDICAL_READ_PERMISSIONS =
176         arrayOf(
177             "android.permission.health.READ_MEDICAL_DATA_ALLERGIES_INTOLERANCES",
178             "android.permission.health.READ_MEDICAL_DATA_CONDITIONS",
179             "android.permission.health.READ_MEDICAL_DATA_LABORATORY_RESULTS",
180             "android.permission.health.READ_MEDICAL_DATA_MEDICATIONS",
181             "android.permission.health.READ_MEDICAL_DATA_PERSONAL_DETAILS",
182             "android.permission.health.READ_MEDICAL_DATA_PRACTITIONER_DETAILS",
183             "android.permission.health.READ_MEDICAL_DATA_PREGNANCY",
184             "android.permission.health.READ_MEDICAL_DATA_PROCEDURES",
185             "android.permission.health.READ_MEDICAL_DATA_SOCIAL_HISTORY",
186             "android.permission.health.READ_MEDICAL_DATA_VACCINES",
187             "android.permission.health.READ_MEDICAL_DATA_VISITS",
188             "android.permission.health.READ_MEDICAL_DATA_VITAL_SIGNS",
189         )
190     val MEDICAL_WRITE_PERMISSIONS = arrayOf("android.permission.health.WRITE_MEDICAL_DATA")
191     val MEDICAL_PERMISSIONS = MEDICAL_READ_PERMISSIONS + MEDICAL_WRITE_PERMISSIONS
192 
193     val MEDICAL_WRITE_AND_OTHERS =
194         MEDICAL_WRITE_PERMISSIONS + FITNESS_PERMISSIONS + ADDITIONAL_PERMISSIONS
195     val HEALTH_PERMISSIONS = FITNESS_PERMISSIONS + ADDITIONAL_PERMISSIONS + MEDICAL_PERMISSIONS
196 
197     /** Represents Category group for HealthConnect data. */
198     enum class HealthDataCategory(
199         val healthPermissionTypes: List<HealthPermissionType>,
200         @StringRes val title: Int,
201         @DrawableRes val icon: Int,
202     ) {
203         ACTIVITY(
204             CategoriesMappers.ACTIVITY_PERMISSION_GROUPS,
205             R.string.activity_category,
206             R.drawable.quantum_gm_ic_directions_run_vd_theme_24,
207         ),
208         BODY_MEASUREMENTS(
209             CategoriesMappers.BODY_MEASUREMENTS_PERMISSION_GROUPS,
210             R.string.body_measurements_category,
211             R.drawable.quantum_gm_ic_straighten_vd_theme_24,
212         ),
213         SLEEP(
214             CategoriesMappers.SLEEP_PERMISSION_GROUPS,
215             R.string.sleep_category,
216             R.drawable.ic_sleep,
217         ),
218         VITALS(
219             CategoriesMappers.VITALS_PERMISSION_GROUPS,
220             R.string.vitals_category,
221             R.drawable.ic_vitals,
222         ),
223         CYCLE_TRACKING(
224             CategoriesMappers.CYCLE_TRACKING_PERMISSION_GROUPS,
225             R.string.cycle_tracking_category,
226             R.drawable.ic_cycle_tracking,
227         ),
228         NUTRITION(
229             CategoriesMappers.NUTRITION_PERMISSION_GROUPS,
230             R.string.nutrition_category,
231             R.drawable.quantum_gm_ic_grocery_vd_theme_24,
232         ),
233         WELLNESS(
234             CategoriesMappers.WELLNESS_PERMISSION_GROUPS,
235             R.string.wellness_category,
236             R.drawable.ic_wellness,
237         ),
238     }
239 
240     /** Permission groups for each {@link HealthDataCategory}. */
241     object CategoriesMappers {
242         val ACTIVITY_PERMISSION_GROUPS =
243             listOf(
244                 HealthPermissionType.PLANNED_EXERCISE,
245                 HealthPermissionType.ACTIVE_CALORIES_BURNED,
246                 HealthPermissionType.ACTIVITY_INTENSITY,
247                 HealthPermissionType.DISTANCE,
248                 HealthPermissionType.ELEVATION_GAINED,
249                 HealthPermissionType.FLOORS_CLIMBED,
250                 HealthPermissionType.POWER,
251                 HealthPermissionType.SPEED,
252                 HealthPermissionType.STEPS,
253                 HealthPermissionType.STEPS_CADENCE,
254                 HealthPermissionType.TOTAL_CALORIES_BURNED,
255                 HealthPermissionType.VO2_MAX,
256                 HealthPermissionType.CYCLING_PEDALING_CADENCE,
257                 HealthPermissionType.WHEELCHAIR_PUSHES,
258                 HealthPermissionType.EXERCISE_SESSION,
259             )
260 
261         val BODY_MEASUREMENTS_PERMISSION_GROUPS =
262             listOf(
263                 HealthPermissionType.BASAL_METABOLIC_RATE,
264                 HealthPermissionType.BODY_FAT,
265                 HealthPermissionType.BODY_WATER_MASS,
266                 HealthPermissionType.BONE_MASS,
267                 HealthPermissionType.HEIGHT,
268                 HealthPermissionType.LEAN_BODY_MASS,
269                 HealthPermissionType.WEIGHT,
270             )
271 
272         val CYCLE_TRACKING_PERMISSION_GROUPS =
273             listOf(
274                 HealthPermissionType.CERVICAL_MUCUS,
275                 HealthPermissionType.MENSTRUATION_FLOW,
276                 HealthPermissionType.MENSTRUATION_PERIOD,
277                 HealthPermissionType.OVULATION_TEST,
278                 HealthPermissionType.INTERMENSTRUAL_BLEEDING,
279                 HealthPermissionType.SEXUAL_ACTIVITY,
280             )
281 
282         val NUTRITION_PERMISSION_GROUPS =
283             listOf(HealthPermissionType.HYDRATION, HealthPermissionType.NUTRITION)
284 
285         val SLEEP_PERMISSION_GROUPS = listOf(HealthPermissionType.SLEEP)
286 
287         val VITALS_PERMISSION_GROUPS =
288             listOf(
289                 HealthPermissionType.BASAL_BODY_TEMPERATURE,
290                 HealthPermissionType.BLOOD_GLUCOSE,
291                 HealthPermissionType.BLOOD_PRESSURE,
292                 HealthPermissionType.BODY_TEMPERATURE,
293                 HealthPermissionType.HEART_RATE,
294                 HealthPermissionType.HEART_RATE_VARIABILITY,
295                 HealthPermissionType.OXYGEN_SATURATION,
296                 HealthPermissionType.RESPIRATORY_RATE,
297                 HealthPermissionType.RESTING_HEART_RATE,
298                 HealthPermissionType.SKIN_TEMPERATURE,
299             )
300 
301         val WELLNESS_PERMISSION_GROUPS = listOf(HealthPermissionType.MINDFULNESS)
302     }
303 
304     enum class HealthPermissionType(
305         val recordClass: KClass<out Record>?,
306         @StringRes val title: Int,
307     ) {
308         // ACTIVITY
309         ACTIVE_CALORIES_BURNED(
310             ActiveCaloriesBurnedRecord::class,
311             R.string.active_calories_burned_label,
312         ),
313         ACTIVITY_INTENSITY(ActivityIntensityRecord::class, R.string.activity_intensity_label),
314         DISTANCE(DistanceRecord::class, R.string.distance_label),
315         ELEVATION_GAINED(ElevationGainedRecord::class, R.string.elevation_gained_label),
316         FLOORS_CLIMBED(FloorsClimbedRecord::class, R.string.floors_climbed_label),
317         STEPS(StepsRecord::class, R.string.steps_label),
318         STEPS_CADENCE(StepsCadenceRecord::class, R.string.steps_cadence_label),
319         TOTAL_CALORIES_BURNED(
320             TotalCaloriesBurnedRecord::class,
321             R.string.total_calories_burned_label,
322         ),
323         VO2_MAX(Vo2MaxRecord::class, R.string.vo2_max_label),
324         WHEELCHAIR_PUSHES(WheelchairPushesRecord::class, R.string.wheelchair_pushes_label),
325         POWER(PowerRecord::class, R.string.power_label),
326         SPEED(SpeedRecord::class, R.string.speed_label),
327         CYCLING_PEDALING_CADENCE(
328             CyclingPedalingCadenceRecord::class,
329             R.string.cycling_pedaling_cadence,
330         ),
331         EXERCISE_SESSION(ExerciseSessionRecord::class, R.string.exercise_session),
332         PLANNED_EXERCISE(PlannedExerciseSessionRecord::class, R.string.training_plans),
333 
334         // BODY_MEASUREMENTS
335         BASAL_METABOLIC_RATE(BasalMetabolicRateRecord::class, R.string.basal_metabolic_rate_label),
336         BODY_FAT(BodyFatRecord::class, R.string.body_fat_label),
337         BODY_WATER_MASS(BodyWaterMassRecord::class, R.string.body_water_mass_label),
338         BONE_MASS(BoneMassRecord::class, R.string.bone_mass_label),
339         HEIGHT(HeightRecord::class, R.string.height_label),
340         LEAN_BODY_MASS(LeanBodyMassRecord::class, R.string.lean_body_mass_label),
341         WEIGHT(WeightRecord::class, R.string.weight_label),
342 
343         // CYCLE_TRACKING
344         CERVICAL_MUCUS(CervicalMucusRecord::class, R.string.cervical_mucus_label),
345         MENSTRUATION_FLOW(MenstruationFlowRecord::class, R.string.menstruation_flow),
346         MENSTRUATION_PERIOD(MenstruationPeriodRecord::class, R.string.menstruation_period),
347         OVULATION_TEST(OvulationTestRecord::class, R.string.ovulation_test_label),
348         SEXUAL_ACTIVITY(SexualActivityRecord::class, R.string.sexual_activity_label),
349         INTERMENSTRUAL_BLEEDING(
350             IntermenstrualBleedingRecord::class,
351             R.string.inter_menstrual_bleeding,
352         ),
353 
354         // NUTRITION
355         HYDRATION(HydrationRecord::class, R.string.hydration_label),
356         NUTRITION(NutritionRecord::class, R.string.nutrition_label),
357 
358         // SLEEP
359         SLEEP(SleepSessionRecord::class, R.string.sleep_label),
360 
361         // VITALS
362         BASAL_BODY_TEMPERATURE(
363             BasalBodyTemperatureRecord::class,
364             R.string.basal_body_temperature_label,
365         ),
366         BLOOD_GLUCOSE(BloodGlucoseRecord::class, R.string.blood_glucose_label),
367         BLOOD_PRESSURE(BloodPressureRecord::class, R.string.blood_pressure_label),
368         BODY_TEMPERATURE(BodyTemperatureRecord::class, R.string.body_temperature_label),
369         HEART_RATE(HeartRateRecord::class, R.string.heart_rate_label),
370         HEART_RATE_VARIABILITY(
371             HeartRateVariabilityRmssdRecord::class,
372             R.string.heart_rate_variability_label,
373         ),
374         OXYGEN_SATURATION(OxygenSaturationRecord::class, R.string.oxygen_saturation_label),
375         RESPIRATORY_RATE(RespiratoryRateRecord::class, R.string.respiratory_rate_label),
376         RESTING_HEART_RATE(RestingHeartRateRecord::class, R.string.resting_heart_rate_label),
377         SKIN_TEMPERATURE(SkinTemperatureRecord::class, R.string.skin_temperature_label),
378 
379         // WELLNESS
380         MINDFULNESS(MindfulnessSessionRecord::class, R.string.mindfulness_label),
381     }
382 }
383