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;
18 
19 import static android.health.connect.Constants.DEFAULT_INT;
20 import static android.health.connect.HealthPermissionCategory.ACTIVE_CALORIES_BURNED;
21 import static android.health.connect.HealthPermissionCategory.BASAL_BODY_TEMPERATURE;
22 import static android.health.connect.HealthPermissionCategory.BASAL_METABOLIC_RATE;
23 import static android.health.connect.HealthPermissionCategory.BLOOD_GLUCOSE;
24 import static android.health.connect.HealthPermissionCategory.BLOOD_PRESSURE;
25 import static android.health.connect.HealthPermissionCategory.BODY_FAT;
26 import static android.health.connect.HealthPermissionCategory.BODY_TEMPERATURE;
27 import static android.health.connect.HealthPermissionCategory.BODY_WATER_MASS;
28 import static android.health.connect.HealthPermissionCategory.BONE_MASS;
29 import static android.health.connect.HealthPermissionCategory.CERVICAL_MUCUS;
30 import static android.health.connect.HealthPermissionCategory.DISTANCE;
31 import static android.health.connect.HealthPermissionCategory.ELEVATION_GAINED;
32 import static android.health.connect.HealthPermissionCategory.EXERCISE;
33 import static android.health.connect.HealthPermissionCategory.FLOORS_CLIMBED;
34 import static android.health.connect.HealthPermissionCategory.HEART_RATE;
35 import static android.health.connect.HealthPermissionCategory.HEART_RATE_VARIABILITY;
36 import static android.health.connect.HealthPermissionCategory.HEIGHT;
37 import static android.health.connect.HealthPermissionCategory.HYDRATION;
38 import static android.health.connect.HealthPermissionCategory.INTERMENSTRUAL_BLEEDING;
39 import static android.health.connect.HealthPermissionCategory.LEAN_BODY_MASS;
40 import static android.health.connect.HealthPermissionCategory.MENSTRUATION;
41 import static android.health.connect.HealthPermissionCategory.MINDFULNESS;
42 import static android.health.connect.HealthPermissionCategory.NUTRITION;
43 import static android.health.connect.HealthPermissionCategory.OVULATION_TEST;
44 import static android.health.connect.HealthPermissionCategory.OXYGEN_SATURATION;
45 import static android.health.connect.HealthPermissionCategory.PLANNED_EXERCISE;
46 import static android.health.connect.HealthPermissionCategory.POWER;
47 import static android.health.connect.HealthPermissionCategory.RESPIRATORY_RATE;
48 import static android.health.connect.HealthPermissionCategory.RESTING_HEART_RATE;
49 import static android.health.connect.HealthPermissionCategory.SEXUAL_ACTIVITY;
50 import static android.health.connect.HealthPermissionCategory.SKIN_TEMPERATURE;
51 import static android.health.connect.HealthPermissionCategory.SLEEP;
52 import static android.health.connect.HealthPermissionCategory.SPEED;
53 import static android.health.connect.HealthPermissionCategory.STEPS;
54 import static android.health.connect.HealthPermissionCategory.TOTAL_CALORIES_BURNED;
55 import static android.health.connect.HealthPermissionCategory.VO2_MAX;
56 import static android.health.connect.HealthPermissionCategory.WEIGHT;
57 import static android.health.connect.HealthPermissionCategory.WHEELCHAIR_PUSHES;
58 import static android.health.connect.MedicalPermissionCategory.IMMUNIZATION;
59 
60 import static com.android.healthfitness.flags.Flags.FLAG_MINDFULNESS;
61 import static com.android.healthfitness.flags.Flags.FLAG_PERSONAL_HEALTH_RECORD;
62 import static com.android.healthfitness.flags.Flags.personalHealthRecord;
63 
64 import android.annotation.FlaggedApi;
65 import android.annotation.NonNull;
66 import android.annotation.Nullable;
67 import android.annotation.SystemApi;
68 import android.content.Context;
69 import android.content.pm.PackageInfo;
70 import android.health.connect.datatypes.ExerciseRoute;
71 import android.util.ArrayMap;
72 import android.util.ArraySet;
73 
74 import java.util.HashSet;
75 import java.util.Map;
76 import java.util.Objects;
77 import java.util.Set;
78 
79 // TODO(b/255340973): consider generate this class.
80 /**
81  * Permissions for accessing the HealthConnect APIs.
82  *
83  * <p>Apps must support {@link android.content.Intent#ACTION_VIEW_PERMISSION_USAGE} with {@link
84  * HealthConnectManager#CATEGORY_HEALTH_PERMISSIONS} category to be granted read/write health data
85  * permissions.
86  */
87 public final class HealthPermissions {
88     /**
89      * Allows an application to grant/revoke health-related permissions.
90      *
91      * <p>Protection level: signature.
92      *
93      * @hide
94      */
95     @SystemApi
96     public static final String MANAGE_HEALTH_PERMISSIONS =
97             "android.permission.MANAGE_HEALTH_PERMISSIONS";
98 
99     // Below permission was earlier declared in HealthConnectManager since it was only permission
100     // used by access logs API, is now declared here along with the other system permission.
101     // Please suggest if it will be ok to have it here.
102     /**
103      * Allows an application to modify health data.
104      *
105      * <p>Protection level: privileged.
106      *
107      * @hide
108      */
109     @SystemApi
110     public static final String MANAGE_HEALTH_DATA_PERMISSION =
111             "android.permission.MANAGE_HEALTH_DATA";
112 
113     /**
114      * Allows an application to launch client onboarding activities responsible for connecting to
115      * Health Connect. This permission can only be held by the system. Client apps that choose to
116      * export an onboarding activity must guard it with this permission so that only the system can
117      * launch it.
118      *
119      * <p>See {@link HealthConnectManager#ACTION_SHOW_ONBOARDING} for the corresponding intent used
120      * by the system to launch onboarding activities.
121      *
122      * <p>Protection level: signature.
123      *
124      * @hide
125      */
126     public static final String START_ONBOARDING = "android.permission.health.START_ONBOARDING";
127 
128     /**
129      * Used for runtime permissions which grant access to Health Connect data.
130      *
131      * @hide
132      */
133     @SystemApi
134     public static final String HEALTH_PERMISSION_GROUP = "android.permission-group.HEALTH";
135 
136     /**
137      * Allows an application to read health data (of any type) in background.
138      *
139      * <p>Protection level: dangerous.
140      */
141     @FlaggedApi("com.android.healthconnect.flags.background_read")
142     public static final String READ_HEALTH_DATA_IN_BACKGROUND =
143             "android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND";
144 
145     /**
146      * Allows an application to read the entire history of health data (of any type).
147      *
148      * <p>Protection level: dangerous.
149      */
150     @FlaggedApi("com.android.healthconnect.flags.history_read")
151     public static final String READ_HEALTH_DATA_HISTORY =
152             "android.permission.health.READ_HEALTH_DATA_HISTORY";
153 
154     /**
155      * Allows an application to read the user's active calories burned data.
156      *
157      * <p>Protection level: dangerous.
158      */
159     public static final String READ_ACTIVE_CALORIES_BURNED =
160             "android.permission.health.READ_ACTIVE_CALORIES_BURNED";
161 
162     /**
163      * Allows an application to read the user's distance data.
164      *
165      * <p>Protection level: dangerous.
166      */
167     public static final String READ_DISTANCE = "android.permission.health.READ_DISTANCE";
168 
169     /**
170      * Allows an application to read the user's elevation gained data.
171      *
172      * <p>Protection level: dangerous.
173      */
174     public static final String READ_ELEVATION_GAINED =
175             "android.permission.health.READ_ELEVATION_GAINED";
176 
177     /**
178      * Allows an application to read the user's exercise data.
179      *
180      * <p>Protection level: dangerous.
181      */
182     public static final String READ_EXERCISE = "android.permission.health.READ_EXERCISE";
183 
184     /**
185      * Allows an application to read any {@link ExerciseRoute}. Not connected with READ_EXERCISE
186      * permission, as it's used only by HealthConnectController to show routes in UI and share one
187      * particular route with third party app after one-time user consent.
188      *
189      * <p>Protection level: signature.
190      *
191      * @hide
192      */
193     public static final String READ_EXERCISE_ROUTE =
194             "android.permission.health.READ_EXERCISE_ROUTE";
195 
196     /**
197      * Allows an application to read {@link ExerciseRoute}.
198      *
199      * <p>This permission can only be granted manually by a user in Health Connect settings or in
200      * the route request activity which can be launched using {@link ACTION_REQUEST_EXERCISE_ROUTE}.
201      * Attempts to request the permission by applications will be ignored.
202      *
203      * <p>Applications should check if the permission has been granted before reading {@link
204      * ExerciseRoute}.
205      *
206      * <p>Protection level: dangerous.
207      */
208     @FlaggedApi("com.android.healthconnect.flags.read_exercise_routes_all_enabled")
209     public static final String READ_EXERCISE_ROUTES =
210             "android.permission.health.READ_EXERCISE_ROUTES";
211 
212     /**
213      * Allows an application to read the user's floors climbed data.
214      *
215      * <p>Protection level: dangerous.
216      */
217     public static final String READ_FLOORS_CLIMBED =
218             "android.permission.health.READ_FLOORS_CLIMBED";
219 
220     /**
221      * Allows an application to read the user's steps data.
222      *
223      * <p>Protection level: dangerous.
224      */
225     public static final String READ_STEPS = "android.permission.health.READ_STEPS";
226 
227     /**
228      * Allows an application to read the user's total calories burned data.
229      *
230      * <p>Protection level: dangerous.
231      */
232     public static final String READ_TOTAL_CALORIES_BURNED =
233             "android.permission.health.READ_TOTAL_CALORIES_BURNED";
234 
235     /**
236      * Allows an application to read the user's vo2 maximum data.
237      *
238      * <p>Protection level: dangerous.
239      */
240     public static final String READ_VO2_MAX = "android.permission.health.READ_VO2_MAX";
241 
242     /**
243      * Allows an application to read the user's wheelchair pushes data.
244      *
245      * <p>Protection level: dangerous.
246      */
247     public static final String READ_WHEELCHAIR_PUSHES =
248             "android.permission.health.READ_WHEELCHAIR_PUSHES";
249 
250     /**
251      * Allows an application to read the user's power data.
252      *
253      * <p>Protection level: dangerous.
254      */
255     public static final String READ_POWER = "android.permission.health.READ_POWER";
256 
257     /**
258      * Allows an application to read the user's speed data.
259      *
260      * <p>Protection level: dangerous.
261      */
262     public static final String READ_SPEED = "android.permission.health.READ_SPEED";
263 
264     /**
265      * Allows an application to read the user's basal metabolic rate data.
266      *
267      * <p>Protection level: dangerous.
268      */
269     public static final String READ_BASAL_METABOLIC_RATE =
270             "android.permission.health.READ_BASAL_METABOLIC_RATE";
271 
272     /**
273      * Allows an application to read the user's body fat data.
274      *
275      * <p>Protection level: dangerous.
276      */
277     public static final String READ_BODY_FAT = "android.permission.health.READ_BODY_FAT";
278 
279     /**
280      * Allows an application to read the user's body water mass data.
281      *
282      * <p>Protection level: dangerous.
283      */
284     public static final String READ_BODY_WATER_MASS =
285             "android.permission.health.READ_BODY_WATER_MASS";
286 
287     /**
288      * Allows an application to read the user's bone mass data.
289      *
290      * <p>Protection level: dangerous.
291      */
292     public static final String READ_BONE_MASS = "android.permission.health.READ_BONE_MASS";
293 
294     /**
295      * Allows an application to read the user's height data.
296      *
297      * <p>Protection level: dangerous.
298      */
299     public static final String READ_HEIGHT = "android.permission.health.READ_HEIGHT";
300 
301     /**
302      * Allows an application to read the user's lean body mass data.
303      *
304      * <p>Protection level: dangerous.
305      */
306     public static final String READ_LEAN_BODY_MASS =
307             "android.permission.health.READ_LEAN_BODY_MASS";
308 
309     /**
310      * Allows an application to read the user's weight data.
311      *
312      * <p>Protection level: dangerous.
313      */
314     public static final String READ_WEIGHT = "android.permission.health.READ_WEIGHT";
315 
316     /**
317      * Allows an application to read the user's cervical mucus data.
318      *
319      * <p>Protection level: dangerous.
320      */
321     public static final String READ_CERVICAL_MUCUS =
322             "android.permission.health.READ_CERVICAL_MUCUS";
323 
324     /**
325      * Allows an application to read the user's menstruation data.
326      *
327      * <p>Protection level: dangerous.
328      */
329     public static final String READ_MENSTRUATION = "android.permission.health.READ_MENSTRUATION";
330 
331     /**
332      * Allows an application to read the user's intermenstrual bleeding data.
333      *
334      * <p>Protection level: dangerous.
335      */
336     public static final String READ_INTERMENSTRUAL_BLEEDING =
337             "android.permission.health.READ_INTERMENSTRUAL_BLEEDING";
338 
339     /**
340      * Allows an application to read the user's ovulation test data.
341      *
342      * <p>Protection level: dangerous.
343      */
344     public static final String READ_OVULATION_TEST =
345             "android.permission.health.READ_OVULATION_TEST";
346 
347     /**
348      * Allows an application to read the user's sexual activity data.
349      *
350      * <p>Protection level: dangerous.
351      */
352     public static final String READ_SEXUAL_ACTIVITY =
353             "android.permission.health.READ_SEXUAL_ACTIVITY";
354 
355     /**
356      * Allows an application to read the user's hydration data.
357      *
358      * <p>Protection level: dangerous.
359      */
360     public static final String READ_HYDRATION = "android.permission.health.READ_HYDRATION";
361 
362     /**
363      * Allows an application to read the user's nutrition data.
364      *
365      * <p>Protection level: dangerous.
366      */
367     public static final String READ_NUTRITION = "android.permission.health.READ_NUTRITION";
368 
369     /**
370      * Allows an application to read the user's sleep data.
371      *
372      * <p>Protection level: dangerous.
373      */
374     public static final String READ_SLEEP = "android.permission.health.READ_SLEEP";
375 
376     /**
377      * Allows an application to read the user's body temperature data.
378      *
379      * <p>Protection level: dangerous.
380      */
381     public static final String READ_BASAL_BODY_TEMPERATURE =
382             "android.permission.health.READ_BASAL_BODY_TEMPERATURE";
383 
384     /**
385      * Allows an application to read the user's blood glucose data.
386      *
387      * <p>Protection level: dangerous.
388      */
389     public static final String READ_BLOOD_GLUCOSE = "android.permission.health.READ_BLOOD_GLUCOSE";
390 
391     /**
392      * Allows an application to read the user's blood pressure data.
393      *
394      * <p>Protection level: dangerous.
395      */
396     public static final String READ_BLOOD_PRESSURE =
397             "android.permission.health.READ_BLOOD_PRESSURE";
398 
399     /**
400      * Allows an application to read the user's body temperature data.
401      *
402      * <p>Protection level: dangerous.
403      */
404     public static final String READ_BODY_TEMPERATURE =
405             "android.permission.health.READ_BODY_TEMPERATURE";
406 
407     /**
408      * Allows an application to read the user's heart rate data.
409      *
410      * <p>Protection level: dangerous.
411      */
412     public static final String READ_HEART_RATE = "android.permission.health.READ_HEART_RATE";
413 
414     /**
415      * Allows an application to read the user's heart rate variability data.
416      *
417      * <p>Protection level: dangerous.
418      */
419     public static final String READ_HEART_RATE_VARIABILITY =
420             "android.permission.health.READ_HEART_RATE_VARIABILITY";
421 
422     /**
423      * Allows an application to read the user's oxygen saturation data.
424      *
425      * <p>Protection level: dangerous.
426      */
427     public static final String READ_OXYGEN_SATURATION =
428             "android.permission.health.READ_OXYGEN_SATURATION";
429 
430     /**
431      * Allows an application to read the user's respiratory rate data.
432      *
433      * <p>Protection level: dangerous.
434      */
435     public static final String READ_RESPIRATORY_RATE =
436             "android.permission.health.READ_RESPIRATORY_RATE";
437 
438     /**
439      * Allows an application to read the user's resting heart rate data.
440      *
441      * <p>Protection level: dangerous.
442      */
443     public static final String READ_RESTING_HEART_RATE =
444             "android.permission.health.READ_RESTING_HEART_RATE";
445 
446     /**
447      * Allows an application to read the user's skin temperature data.
448      *
449      * <p>Protection level: dangerous.
450      */
451     @FlaggedApi("com.android.healthconnect.flags.skin_temperature")
452     public static final String READ_SKIN_TEMPERATURE =
453             "android.permission.health.READ_SKIN_TEMPERATURE";
454 
455     /**
456      * Allows an application to read the user's training plan data.
457      *
458      * <p>Protection level: dangerous.
459      */
460     @FlaggedApi("com.android.healthconnect.flags.training_plans")
461     public static final String READ_PLANNED_EXERCISE =
462             "android.permission.health.READ_PLANNED_EXERCISE";
463 
464     /**
465      * Allows an application to read user's mindfulness data.
466      *
467      * <p>Protection level: dangerous.
468      */
469     @FlaggedApi(FLAG_MINDFULNESS)
470     public static final String READ_MINDFULNESS = "android.permission.health.READ_MINDFULNESS";
471 
472     /**
473      * Allows an application to write the user's calories burned data.
474      *
475      * <p>Protection level: dangerous.
476      */
477     public static final String WRITE_ACTIVE_CALORIES_BURNED =
478             "android.permission.health.WRITE_ACTIVE_CALORIES_BURNED";
479 
480     /**
481      * Allows an application to write the user's distance data.
482      *
483      * <p>Protection level: dangerous.
484      */
485     public static final String WRITE_DISTANCE = "android.permission.health.WRITE_DISTANCE";
486 
487     /**
488      * Allows an application to write the user's elevation gained data.
489      *
490      * <p>Protection level: dangerous.
491      */
492     public static final String WRITE_ELEVATION_GAINED =
493             "android.permission.health.WRITE_ELEVATION_GAINED";
494 
495     /**
496      * Allows an application to write the user's exercise data. Additional permission {@link
497      * HealthPermissions#WRITE_EXERCISE_ROUTE} is required to write user's exercise route.
498      *
499      * <p>Protection level: dangerous.
500      */
501     public static final String WRITE_EXERCISE = "android.permission.health.WRITE_EXERCISE";
502 
503     /**
504      * Allows an application to write the user's exercise route.
505      *
506      * <p>Protection level: dangerous.
507      */
508     public static final String WRITE_EXERCISE_ROUTE =
509             "android.permission.health.WRITE_EXERCISE_ROUTE";
510 
511     /**
512      * Allows an application to write the user's floors climbed data.
513      *
514      * <p>Protection level: dangerous.
515      */
516     public static final String WRITE_FLOORS_CLIMBED =
517             "android.permission.health.WRITE_FLOORS_CLIMBED";
518 
519     /**
520      * Allows an application to write the user's steps data.
521      *
522      * <p>Protection level: dangerous.
523      */
524     public static final String WRITE_STEPS = "android.permission.health.WRITE_STEPS";
525 
526     /**
527      * Allows an application to write the user's total calories burned data.
528      *
529      * <p>Protection level: dangerous.
530      */
531     public static final String WRITE_TOTAL_CALORIES_BURNED =
532             "android.permission.health.WRITE_TOTAL_CALORIES_BURNED";
533 
534     /**
535      * Allows an application to write the user's vo2 maximum data.
536      *
537      * <p>Protection level: dangerous.
538      */
539     public static final String WRITE_VO2_MAX = "android.permission.health.WRITE_VO2_MAX";
540 
541     /**
542      * Allows an application to write the user's wheelchair pushes data.
543      *
544      * <p>Protection level: dangerous.
545      */
546     public static final String WRITE_WHEELCHAIR_PUSHES =
547             "android.permission.health.WRITE_WHEELCHAIR_PUSHES";
548 
549     /**
550      * Allows an application to write the user's power data.
551      *
552      * <p>Protection level: dangerous.
553      */
554     public static final String WRITE_POWER = "android.permission.health.WRITE_POWER";
555 
556     /**
557      * Allows an application to write the user's speed data.
558      *
559      * <p>Protection level: dangerous.
560      */
561     public static final String WRITE_SPEED = "android.permission.health.WRITE_SPEED";
562 
563     /**
564      * Allows an application to write the user's basal metabolic rate data.
565      *
566      * <p>Protection level: dangerous.
567      */
568     public static final String WRITE_BASAL_METABOLIC_RATE =
569             "android.permission.health.WRITE_BASAL_METABOLIC_RATE";
570 
571     /**
572      * Allows an application to write the user's body fat data.
573      *
574      * <p>Protection level: dangerous.
575      */
576     public static final String WRITE_BODY_FAT = "android.permission.health.WRITE_BODY_FAT";
577 
578     /**
579      * Allows an application to write the user's body water mass data.
580      *
581      * <p>Protection level: dangerous.
582      */
583     public static final String WRITE_BODY_WATER_MASS =
584             "android.permission.health.WRITE_BODY_WATER_MASS";
585 
586     /**
587      * Allows an application to write the user's bone mass data.
588      *
589      * <p>Protection level: dangerous.
590      */
591     public static final String WRITE_BONE_MASS = "android.permission.health.WRITE_BONE_MASS";
592 
593     /**
594      * Allows an application to write the user's height data.
595      *
596      * <p>Protection level: dangerous.
597      */
598     public static final String WRITE_HEIGHT = "android.permission.health.WRITE_HEIGHT";
599 
600     /**
601      * Allows an application to write the user's lean body mass data.
602      *
603      * <p>Protection level: dangerous.
604      */
605     public static final String WRITE_LEAN_BODY_MASS =
606             "android.permission.health.WRITE_LEAN_BODY_MASS";
607 
608     /**
609      * Allows an application to write the user's weight data.
610      *
611      * <p>Protection level: dangerous.
612      */
613     public static final String WRITE_WEIGHT = "android.permission.health.WRITE_WEIGHT";
614 
615     /**
616      * Allows an application to write the user's cervical mucus data.
617      *
618      * <p>Protection level: dangerous.
619      */
620     public static final String WRITE_CERVICAL_MUCUS =
621             "android.permission.health.WRITE_CERVICAL_MUCUS";
622 
623     /**
624      * Allows an application to write the user's menstruation data.
625      *
626      * <p>Protection level: dangerous.
627      */
628     public static final String WRITE_MENSTRUATION = "android.permission.health.WRITE_MENSTRUATION";
629 
630     /**
631      * Allows an application to write the user's intermenstrual bleeding data.
632      *
633      * <p>Protection level: dangerous.
634      */
635     public static final String WRITE_INTERMENSTRUAL_BLEEDING =
636             "android.permission.health.WRITE_INTERMENSTRUAL_BLEEDING";
637 
638     /**
639      * Allows an application to write the user's ovulation test data.
640      *
641      * <p>Protection level: dangerous.
642      */
643     public static final String WRITE_OVULATION_TEST =
644             "android.permission.health.WRITE_OVULATION_TEST";
645 
646     /**
647      * Allows an application to write the user's sexual activity data.
648      *
649      * <p>Protection level: dangerous.
650      */
651     public static final String WRITE_SEXUAL_ACTIVITY =
652             "android.permission.health.WRITE_SEXUAL_ACTIVITY";
653 
654     /**
655      * Allows an application to write the user's hydration data.
656      *
657      * <p>Protection level: dangerous.
658      */
659     public static final String WRITE_HYDRATION = "android.permission.health.WRITE_HYDRATION";
660 
661     /**
662      * Allows an application to write the user's nutrition data.
663      *
664      * <p>Protection level: dangerous.
665      */
666     public static final String WRITE_NUTRITION = "android.permission.health.WRITE_NUTRITION";
667 
668     /**
669      * Allows an application to write the user's sleep data.
670      *
671      * <p>Protection level: dangerous.
672      */
673     public static final String WRITE_SLEEP = "android.permission.health.WRITE_SLEEP";
674 
675     /**
676      * Allows an application to write the user's basal body temperature data.
677      *
678      * <p>Protection level: dangerous.
679      */
680     public static final String WRITE_BASAL_BODY_TEMPERATURE =
681             "android.permission.health.WRITE_BASAL_BODY_TEMPERATURE";
682 
683     /**
684      * Allows an application to write the user's blood glucose data.
685      *
686      * <p>Protection level: dangerous.
687      */
688     public static final String WRITE_BLOOD_GLUCOSE =
689             "android.permission.health.WRITE_BLOOD_GLUCOSE";
690 
691     /**
692      * Allows an application to write the user's blood pressure data.
693      *
694      * <p>Protection level: dangerous.
695      */
696     public static final String WRITE_BLOOD_PRESSURE =
697             "android.permission.health.WRITE_BLOOD_PRESSURE";
698 
699     /**
700      * Allows an application to write the user's body temperature data.
701      *
702      * <p>Protection level: dangerous.
703      */
704     public static final String WRITE_BODY_TEMPERATURE =
705             "android.permission.health.WRITE_BODY_TEMPERATURE";
706 
707     /**
708      * Allows an application to write the user's heart rate data.
709      *
710      * <p>Protection level: dangerous.
711      */
712     public static final String WRITE_HEART_RATE = "android.permission.health.WRITE_HEART_RATE";
713 
714     /**
715      * Allows an application to write the user's heart rate variability data.
716      *
717      * <p>Protection level: dangerous.
718      */
719     public static final String WRITE_HEART_RATE_VARIABILITY =
720             "android.permission.health.WRITE_HEART_RATE_VARIABILITY";
721 
722     /**
723      * Allows an application to write the user's oxygen saturation data.
724      *
725      * <p>Protection level: dangerous.
726      */
727     public static final String WRITE_OXYGEN_SATURATION =
728             "android.permission.health.WRITE_OXYGEN_SATURATION";
729 
730     /**
731      * Allows an application to write the user's respiratory rate data.
732      *
733      * <p>Protection level: dangerous.
734      */
735     public static final String WRITE_RESPIRATORY_RATE =
736             "android.permission.health.WRITE_RESPIRATORY_RATE";
737 
738     /**
739      * Allows an application to write the user's resting heart rate data.
740      *
741      * <p>Protection level: dangerous.
742      */
743     public static final String WRITE_RESTING_HEART_RATE =
744             "android.permission.health.WRITE_RESTING_HEART_RATE";
745 
746     /**
747      * Allows an application to write the user's skin temperature data.
748      *
749      * <p>Protection level: dangerous.
750      */
751     @FlaggedApi("com.android.healthconnect.flags.skin_temperature")
752     public static final String WRITE_SKIN_TEMPERATURE =
753             "android.permission.health.WRITE_SKIN_TEMPERATURE";
754 
755     /**
756      * Allows an application to write the user's training plan data.
757      *
758      * <p>Protection level: dangerous.
759      */
760     @FlaggedApi("com.android.healthconnect.flags.training_plans")
761     public static final String WRITE_PLANNED_EXERCISE =
762             "android.permission.health.WRITE_PLANNED_EXERCISE";
763 
764     /**
765      * Allows an application to write user's mindfulness data.
766      *
767      * <p>Protection level: dangerous.
768      */
769     @FlaggedApi(FLAG_MINDFULNESS)
770     public static final String WRITE_MINDFULNESS = "android.permission.health.WRITE_MINDFULNESS";
771 
772     /** Personal Health Record permissions */
773 
774     /**
775      * Allows an application to read the user's immunization data.
776      *
777      * <p>Protection level: dangerous.
778      */
779     @FlaggedApi(FLAG_PERSONAL_HEALTH_RECORD)
780     public static final String READ_MEDICAL_DATA_IMMUNIZATION =
781             "android.permission.health.READ_MEDICAL_DATA_IMMUNIZATION";
782 
783     /**
784      * Allows an application to write the user's medical data.
785      *
786      * <p>Protection level: dangerous.
787      */
788     @FlaggedApi(FLAG_PERSONAL_HEALTH_RECORD)
789     public static final String WRITE_MEDICAL_DATA = "android.permission.health.WRITE_MEDICAL_DATA";
790 
791     private static final Set<String> sWritePermissionsSet =
792             new ArraySet<>(
793                     Set.of(
794                             WRITE_ACTIVE_CALORIES_BURNED,
795                             WRITE_DISTANCE,
796                             WRITE_ELEVATION_GAINED,
797                             WRITE_EXERCISE,
798                             WRITE_FLOORS_CLIMBED,
799                             WRITE_STEPS,
800                             WRITE_TOTAL_CALORIES_BURNED,
801                             WRITE_VO2_MAX,
802                             WRITE_WHEELCHAIR_PUSHES,
803                             WRITE_POWER,
804                             WRITE_SPEED,
805                             WRITE_BASAL_METABOLIC_RATE,
806                             WRITE_BODY_FAT,
807                             WRITE_BODY_WATER_MASS,
808                             WRITE_BONE_MASS,
809                             WRITE_HEIGHT,
810                             WRITE_LEAN_BODY_MASS,
811                             WRITE_WEIGHT,
812                             WRITE_CERVICAL_MUCUS,
813                             WRITE_MENSTRUATION,
814                             WRITE_INTERMENSTRUAL_BLEEDING,
815                             WRITE_OVULATION_TEST,
816                             WRITE_SEXUAL_ACTIVITY,
817                             WRITE_HYDRATION,
818                             WRITE_NUTRITION,
819                             WRITE_SLEEP,
820                             WRITE_BASAL_BODY_TEMPERATURE,
821                             WRITE_BLOOD_GLUCOSE,
822                             WRITE_BLOOD_PRESSURE,
823                             WRITE_BODY_TEMPERATURE,
824                             WRITE_HEART_RATE,
825                             WRITE_HEART_RATE_VARIABILITY,
826                             WRITE_OXYGEN_SATURATION,
827                             WRITE_RESPIRATORY_RATE,
828                             WRITE_RESTING_HEART_RATE,
829                             WRITE_SKIN_TEMPERATURE,
830                             WRITE_PLANNED_EXERCISE));
831 
832     private static final Map<String, Integer> sWriteHealthPermissionToHealthDataCategoryMap =
833             new ArrayMap<>();
834     private static final Map<Integer, String> sHealthCategoryToReadPermissionMap = new ArrayMap<>();
835     private static final Map<Integer, String> sHealthCategoryToWritePermissionMap =
836             new ArrayMap<>();
837 
838     private static final Map<Integer, String[]> sDataCategoryToWritePermissionsMap =
839             new ArrayMap<>();
840 
841     private static final Map<Integer, String> sMedicalCategoryToReadPermissionMap =
842             new ArrayMap<>();
843 
HealthPermissions()844     private HealthPermissions() {}
845 
846     /**
847      * @return true if {@code permissionName} is a write-permission
848      * @hide
849      */
isWritePermission(@onNull String permissionName)850     public static boolean isWritePermission(@NonNull String permissionName) {
851         Objects.requireNonNull(permissionName);
852 
853         return sWritePermissionsSet.contains(permissionName);
854     }
855 
856     /**
857      * @return {@link HealthDataCategory} for a WRITE {@code permissionName}. -1 if permission
858      *     category for {@code permissionName} is not found (or if {@code permissionName} is READ)
859      * @hide
860      */
861     @HealthDataCategory.Type
getHealthDataCategoryForWritePermission(@ullable String permissionName)862     public static int getHealthDataCategoryForWritePermission(@Nullable String permissionName) {
863         if (sWriteHealthPermissionToHealthDataCategoryMap.isEmpty()) {
864             populateWriteHealthPermissionToHealthDataCategoryMap();
865         }
866 
867         return sWriteHealthPermissionToHealthDataCategoryMap.getOrDefault(
868                 permissionName, DEFAULT_INT);
869     }
870 
871     /**
872      * @return {@link HealthDataCategory} for {@code permissionName}. -1 if permission category for
873      *     {@code permissionName} is not found
874      * @hide
875      */
getWriteHealthPermissionsFor(@ealthDataCategory.Type int dataCategory)876     public static String[] getWriteHealthPermissionsFor(@HealthDataCategory.Type int dataCategory) {
877         if (sDataCategoryToWritePermissionsMap.isEmpty()) {
878             populateWriteHealthPermissionToHealthDataCategoryMap();
879         }
880 
881         return sDataCategoryToWritePermissionsMap.getOrDefault(dataCategory, new String[] {});
882     }
883 
884     /** @hide */
885     @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression
getHealthReadPermission( @ealthPermissionCategory.Type int permissionCategory)886     public static String getHealthReadPermission(
887             @HealthPermissionCategory.Type int permissionCategory) {
888         if (sHealthCategoryToReadPermissionMap.isEmpty()) {
889             populateHealthPermissionToHealthPermissionCategoryMap();
890         }
891 
892         return sHealthCategoryToReadPermissionMap.get(permissionCategory);
893     }
894 
895     /** @hide */
getHealthWritePermission( @ealthPermissionCategory.Type int permissionCategory)896     public static String getHealthWritePermission(
897             @HealthPermissionCategory.Type int permissionCategory) {
898         if (sHealthCategoryToWritePermissionMap.isEmpty()) {
899             populateHealthPermissionToHealthPermissionCategoryMap();
900         }
901 
902         String healthWritePermission = sHealthCategoryToWritePermissionMap.get(permissionCategory);
903         Objects.requireNonNull(
904                 healthWritePermission,
905                 "Health write permission not found for "
906                         + "PermissionCategory : "
907                         + permissionCategory);
908         return healthWritePermission;
909     }
910 
911     /** @hide */
getMedicalReadPermission( @edicalPermissionCategory.Type int permissionCategory)912     public static String getMedicalReadPermission(
913             @MedicalPermissionCategory.Type int permissionCategory) {
914         populateReadMedicalPermissionsToMedicalPermissionCategoryMap();
915         String medicalReadPermission = sMedicalCategoryToReadPermissionMap.get(permissionCategory);
916         Objects.requireNonNull(
917                 medicalReadPermission,
918                 "Medical read permission not found for PermissionCategory: " + permissionCategory);
919 
920         return medicalReadPermission;
921     }
922 
923     /**
924      * Returns all medical permissions (read and write).
925      *
926      * @hide
927      */
getAllMedicalPermissions()928     public static Set<String> getAllMedicalPermissions() {
929         if (!personalHealthRecord()) {
930             throw new UnsupportedOperationException("getAllMedicalPermissions is not supported");
931         }
932 
933         populateReadMedicalPermissionsToMedicalPermissionCategoryMap();
934         Set<String> permissions = new HashSet<>(sMedicalCategoryToReadPermissionMap.values());
935         permissions.add(WRITE_MEDICAL_DATA);
936         return permissions;
937     }
938 
939     /**
940      * Returns a set of dataCategories for which this package has WRITE permissions
941      *
942      * @hide
943      */
944     @NonNull
getDataCategoriesWithWritePermissionsForPackage( @onNull PackageInfo packageInfo, @NonNull Context context)945     public static Set<Integer> getDataCategoriesWithWritePermissionsForPackage(
946             @NonNull PackageInfo packageInfo, @NonNull Context context) {
947 
948         Set<Integer> dataCategoriesWithPermissions = new HashSet<>();
949 
950         for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
951             String currPerm = packageInfo.requestedPermissions[i];
952             if (!HealthConnectManager.isHealthPermission(context, currPerm)) {
953                 continue;
954             }
955             if ((packageInfo.requestedPermissionsFlags[i]
956                             & PackageInfo.REQUESTED_PERMISSION_GRANTED)
957                     == 0) {
958                 continue;
959             }
960 
961             int dataCategory = getHealthDataCategoryForWritePermission(currPerm);
962             if (dataCategory >= 0) {
963                 dataCategoriesWithPermissions.add(dataCategory);
964             }
965         }
966 
967         return dataCategoriesWithPermissions;
968     }
969 
970     /**
971      * Returns true if this package has at least one granted WRITE permission for this category.
972      *
973      * @hide
974      */
getPackageHasWriteHealthPermissionsForCategory( @onNull PackageInfo packageInfo, @HealthDataCategory.Type int dataCategory, @NonNull Context context)975     public static boolean getPackageHasWriteHealthPermissionsForCategory(
976             @NonNull PackageInfo packageInfo,
977             @HealthDataCategory.Type int dataCategory,
978             @NonNull Context context) {
979         return getDataCategoriesWithWritePermissionsForPackage(packageInfo, context)
980                 .contains(dataCategory);
981     }
982 
populateHealthPermissionToHealthPermissionCategoryMap()983     private static synchronized void populateHealthPermissionToHealthPermissionCategoryMap() {
984         if (!sHealthCategoryToWritePermissionMap.isEmpty()) {
985             return;
986         }
987 
988         // Populate permission category to write permission map
989         sHealthCategoryToWritePermissionMap.put(
990                 ACTIVE_CALORIES_BURNED, WRITE_ACTIVE_CALORIES_BURNED);
991         sHealthCategoryToWritePermissionMap.put(DISTANCE, WRITE_DISTANCE);
992         sHealthCategoryToWritePermissionMap.put(ELEVATION_GAINED, WRITE_ELEVATION_GAINED);
993         sHealthCategoryToWritePermissionMap.put(EXERCISE, WRITE_EXERCISE);
994         sHealthCategoryToWritePermissionMap.put(FLOORS_CLIMBED, WRITE_FLOORS_CLIMBED);
995         sHealthCategoryToWritePermissionMap.put(STEPS, WRITE_STEPS);
996         sHealthCategoryToWritePermissionMap.put(TOTAL_CALORIES_BURNED, WRITE_TOTAL_CALORIES_BURNED);
997         sHealthCategoryToWritePermissionMap.put(VO2_MAX, WRITE_VO2_MAX);
998         sHealthCategoryToWritePermissionMap.put(WHEELCHAIR_PUSHES, WRITE_WHEELCHAIR_PUSHES);
999         sHealthCategoryToWritePermissionMap.put(POWER, WRITE_POWER);
1000         sHealthCategoryToWritePermissionMap.put(SPEED, WRITE_SPEED);
1001         sHealthCategoryToWritePermissionMap.put(BASAL_METABOLIC_RATE, WRITE_BASAL_METABOLIC_RATE);
1002         sHealthCategoryToWritePermissionMap.put(BODY_FAT, WRITE_BODY_FAT);
1003         sHealthCategoryToWritePermissionMap.put(BODY_WATER_MASS, WRITE_BODY_WATER_MASS);
1004         sHealthCategoryToWritePermissionMap.put(BONE_MASS, WRITE_BONE_MASS);
1005         sHealthCategoryToWritePermissionMap.put(HEIGHT, WRITE_HEIGHT);
1006         sHealthCategoryToWritePermissionMap.put(LEAN_BODY_MASS, WRITE_LEAN_BODY_MASS);
1007         sHealthCategoryToWritePermissionMap.put(WEIGHT, WRITE_WEIGHT);
1008         sHealthCategoryToWritePermissionMap.put(CERVICAL_MUCUS, WRITE_CERVICAL_MUCUS);
1009         sHealthCategoryToWritePermissionMap.put(MENSTRUATION, WRITE_MENSTRUATION);
1010         sHealthCategoryToWritePermissionMap.put(
1011                 INTERMENSTRUAL_BLEEDING, WRITE_INTERMENSTRUAL_BLEEDING);
1012         sHealthCategoryToWritePermissionMap.put(OVULATION_TEST, WRITE_OVULATION_TEST);
1013         sHealthCategoryToWritePermissionMap.put(SEXUAL_ACTIVITY, WRITE_SEXUAL_ACTIVITY);
1014         sHealthCategoryToWritePermissionMap.put(HYDRATION, WRITE_HYDRATION);
1015         sHealthCategoryToWritePermissionMap.put(NUTRITION, WRITE_NUTRITION);
1016         sHealthCategoryToWritePermissionMap.put(SLEEP, WRITE_SLEEP);
1017         sHealthCategoryToWritePermissionMap.put(
1018                 BASAL_BODY_TEMPERATURE, WRITE_BASAL_BODY_TEMPERATURE);
1019         sHealthCategoryToWritePermissionMap.put(BLOOD_GLUCOSE, WRITE_BLOOD_GLUCOSE);
1020         sHealthCategoryToWritePermissionMap.put(BLOOD_PRESSURE, WRITE_BLOOD_PRESSURE);
1021         sHealthCategoryToWritePermissionMap.put(BODY_TEMPERATURE, WRITE_BODY_TEMPERATURE);
1022         sHealthCategoryToWritePermissionMap.put(HEART_RATE, WRITE_HEART_RATE);
1023         sHealthCategoryToWritePermissionMap.put(
1024                 HEART_RATE_VARIABILITY, WRITE_HEART_RATE_VARIABILITY);
1025         sHealthCategoryToWritePermissionMap.put(OXYGEN_SATURATION, WRITE_OXYGEN_SATURATION);
1026         sHealthCategoryToWritePermissionMap.put(RESPIRATORY_RATE, WRITE_RESPIRATORY_RATE);
1027         sHealthCategoryToWritePermissionMap.put(RESTING_HEART_RATE, WRITE_RESTING_HEART_RATE);
1028         sHealthCategoryToWritePermissionMap.put(SKIN_TEMPERATURE, WRITE_SKIN_TEMPERATURE);
1029         sHealthCategoryToWritePermissionMap.put(PLANNED_EXERCISE, WRITE_PLANNED_EXERCISE);
1030         sHealthCategoryToWritePermissionMap.put(MINDFULNESS, WRITE_MINDFULNESS);
1031 
1032         // Populate permission category to read permission map
1033         sHealthCategoryToReadPermissionMap.put(ACTIVE_CALORIES_BURNED, READ_ACTIVE_CALORIES_BURNED);
1034         sHealthCategoryToReadPermissionMap.put(DISTANCE, READ_DISTANCE);
1035         sHealthCategoryToReadPermissionMap.put(ELEVATION_GAINED, READ_ELEVATION_GAINED);
1036         sHealthCategoryToReadPermissionMap.put(EXERCISE, READ_EXERCISE);
1037         sHealthCategoryToReadPermissionMap.put(FLOORS_CLIMBED, READ_FLOORS_CLIMBED);
1038         sHealthCategoryToReadPermissionMap.put(STEPS, READ_STEPS);
1039         sHealthCategoryToReadPermissionMap.put(TOTAL_CALORIES_BURNED, READ_TOTAL_CALORIES_BURNED);
1040         sHealthCategoryToReadPermissionMap.put(VO2_MAX, READ_VO2_MAX);
1041         sHealthCategoryToReadPermissionMap.put(WHEELCHAIR_PUSHES, READ_WHEELCHAIR_PUSHES);
1042         sHealthCategoryToReadPermissionMap.put(POWER, READ_POWER);
1043         sHealthCategoryToReadPermissionMap.put(SPEED, READ_SPEED);
1044         sHealthCategoryToReadPermissionMap.put(BASAL_METABOLIC_RATE, READ_BASAL_METABOLIC_RATE);
1045         sHealthCategoryToReadPermissionMap.put(BODY_FAT, READ_BODY_FAT);
1046         sHealthCategoryToReadPermissionMap.put(BODY_WATER_MASS, READ_BODY_WATER_MASS);
1047         sHealthCategoryToReadPermissionMap.put(BONE_MASS, READ_BONE_MASS);
1048         sHealthCategoryToReadPermissionMap.put(HEIGHT, READ_HEIGHT);
1049         sHealthCategoryToReadPermissionMap.put(LEAN_BODY_MASS, READ_LEAN_BODY_MASS);
1050         sHealthCategoryToReadPermissionMap.put(WEIGHT, READ_WEIGHT);
1051         sHealthCategoryToReadPermissionMap.put(CERVICAL_MUCUS, READ_CERVICAL_MUCUS);
1052         sHealthCategoryToReadPermissionMap.put(MENSTRUATION, READ_MENSTRUATION);
1053         sHealthCategoryToReadPermissionMap.put(
1054                 INTERMENSTRUAL_BLEEDING, READ_INTERMENSTRUAL_BLEEDING);
1055         sHealthCategoryToReadPermissionMap.put(OVULATION_TEST, READ_OVULATION_TEST);
1056         sHealthCategoryToReadPermissionMap.put(SEXUAL_ACTIVITY, READ_SEXUAL_ACTIVITY);
1057         sHealthCategoryToReadPermissionMap.put(HYDRATION, READ_HYDRATION);
1058         sHealthCategoryToReadPermissionMap.put(NUTRITION, READ_NUTRITION);
1059         sHealthCategoryToReadPermissionMap.put(SLEEP, READ_SLEEP);
1060         sHealthCategoryToReadPermissionMap.put(BASAL_BODY_TEMPERATURE, READ_BASAL_BODY_TEMPERATURE);
1061         sHealthCategoryToReadPermissionMap.put(BLOOD_GLUCOSE, READ_BLOOD_GLUCOSE);
1062         sHealthCategoryToReadPermissionMap.put(BLOOD_PRESSURE, READ_BLOOD_PRESSURE);
1063         sHealthCategoryToReadPermissionMap.put(BODY_TEMPERATURE, READ_BODY_TEMPERATURE);
1064         sHealthCategoryToReadPermissionMap.put(HEART_RATE, READ_HEART_RATE);
1065         sHealthCategoryToReadPermissionMap.put(HEART_RATE_VARIABILITY, READ_HEART_RATE_VARIABILITY);
1066         sHealthCategoryToReadPermissionMap.put(OXYGEN_SATURATION, READ_OXYGEN_SATURATION);
1067         sHealthCategoryToReadPermissionMap.put(RESPIRATORY_RATE, READ_RESPIRATORY_RATE);
1068         sHealthCategoryToReadPermissionMap.put(RESTING_HEART_RATE, READ_RESTING_HEART_RATE);
1069         sHealthCategoryToReadPermissionMap.put(SKIN_TEMPERATURE, READ_SKIN_TEMPERATURE);
1070         sHealthCategoryToReadPermissionMap.put(PLANNED_EXERCISE, READ_PLANNED_EXERCISE);
1071         sHealthCategoryToReadPermissionMap.put(MINDFULNESS, READ_MINDFULNESS);
1072     }
1073 
populateWriteHealthPermissionToHealthDataCategoryMap()1074     private static synchronized void populateWriteHealthPermissionToHealthDataCategoryMap() {
1075         if (!sWriteHealthPermissionToHealthDataCategoryMap.isEmpty()) {
1076             return;
1077         }
1078 
1079         // Write permissions
1080         sWriteHealthPermissionToHealthDataCategoryMap.put(
1081                 WRITE_ACTIVE_CALORIES_BURNED, HealthDataCategory.ACTIVITY);
1082         sWriteHealthPermissionToHealthDataCategoryMap.put(
1083                 WRITE_DISTANCE, HealthDataCategory.ACTIVITY);
1084         sWriteHealthPermissionToHealthDataCategoryMap.put(
1085                 WRITE_ELEVATION_GAINED, HealthDataCategory.ACTIVITY);
1086         sWriteHealthPermissionToHealthDataCategoryMap.put(
1087                 WRITE_EXERCISE, HealthDataCategory.ACTIVITY);
1088         sWriteHealthPermissionToHealthDataCategoryMap.put(
1089                 WRITE_PLANNED_EXERCISE, HealthDataCategory.ACTIVITY);
1090         sWriteHealthPermissionToHealthDataCategoryMap.put(
1091                 WRITE_FLOORS_CLIMBED, HealthDataCategory.ACTIVITY);
1092         sWriteHealthPermissionToHealthDataCategoryMap.put(WRITE_STEPS, HealthDataCategory.ACTIVITY);
1093         sWriteHealthPermissionToHealthDataCategoryMap.put(
1094                 WRITE_TOTAL_CALORIES_BURNED, HealthDataCategory.ACTIVITY);
1095         sWriteHealthPermissionToHealthDataCategoryMap.put(
1096                 WRITE_VO2_MAX, HealthDataCategory.ACTIVITY);
1097         sWriteHealthPermissionToHealthDataCategoryMap.put(
1098                 WRITE_WHEELCHAIR_PUSHES, HealthDataCategory.ACTIVITY);
1099         sWriteHealthPermissionToHealthDataCategoryMap.put(WRITE_POWER, HealthDataCategory.ACTIVITY);
1100         sWriteHealthPermissionToHealthDataCategoryMap.put(WRITE_SPEED, HealthDataCategory.ACTIVITY);
1101 
1102         sWriteHealthPermissionToHealthDataCategoryMap.put(
1103                 WRITE_BASAL_METABOLIC_RATE, HealthDataCategory.BODY_MEASUREMENTS);
1104         sWriteHealthPermissionToHealthDataCategoryMap.put(
1105                 WRITE_BODY_FAT, HealthDataCategory.BODY_MEASUREMENTS);
1106         sWriteHealthPermissionToHealthDataCategoryMap.put(
1107                 WRITE_BODY_WATER_MASS, HealthDataCategory.BODY_MEASUREMENTS);
1108         sWriteHealthPermissionToHealthDataCategoryMap.put(
1109                 WRITE_BONE_MASS, HealthDataCategory.BODY_MEASUREMENTS);
1110         sWriteHealthPermissionToHealthDataCategoryMap.put(
1111                 WRITE_HEIGHT, HealthDataCategory.BODY_MEASUREMENTS);
1112         sWriteHealthPermissionToHealthDataCategoryMap.put(
1113                 WRITE_LEAN_BODY_MASS, HealthDataCategory.BODY_MEASUREMENTS);
1114         sWriteHealthPermissionToHealthDataCategoryMap.put(
1115                 WRITE_WEIGHT, HealthDataCategory.BODY_MEASUREMENTS);
1116 
1117         sWriteHealthPermissionToHealthDataCategoryMap.put(
1118                 WRITE_CERVICAL_MUCUS, HealthDataCategory.CYCLE_TRACKING);
1119         sWriteHealthPermissionToHealthDataCategoryMap.put(
1120                 WRITE_MENSTRUATION, HealthDataCategory.CYCLE_TRACKING);
1121         sWriteHealthPermissionToHealthDataCategoryMap.put(
1122                 WRITE_OVULATION_TEST, HealthDataCategory.CYCLE_TRACKING);
1123         sWriteHealthPermissionToHealthDataCategoryMap.put(
1124                 WRITE_SEXUAL_ACTIVITY, HealthDataCategory.CYCLE_TRACKING);
1125         sWriteHealthPermissionToHealthDataCategoryMap.put(
1126                 WRITE_INTERMENSTRUAL_BLEEDING, HealthDataCategory.CYCLE_TRACKING);
1127 
1128         sWriteHealthPermissionToHealthDataCategoryMap.put(
1129                 WRITE_HYDRATION, HealthDataCategory.NUTRITION);
1130         sWriteHealthPermissionToHealthDataCategoryMap.put(
1131                 WRITE_NUTRITION, HealthDataCategory.NUTRITION);
1132         sWriteHealthPermissionToHealthDataCategoryMap.put(WRITE_SLEEP, HealthDataCategory.SLEEP);
1133 
1134         sWriteHealthPermissionToHealthDataCategoryMap.put(
1135                 WRITE_BASAL_BODY_TEMPERATURE, HealthDataCategory.VITALS);
1136         sWriteHealthPermissionToHealthDataCategoryMap.put(
1137                 WRITE_SKIN_TEMPERATURE, HealthDataCategory.VITALS);
1138         sWriteHealthPermissionToHealthDataCategoryMap.put(
1139                 WRITE_BLOOD_GLUCOSE, HealthDataCategory.VITALS);
1140         sWriteHealthPermissionToHealthDataCategoryMap.put(
1141                 WRITE_BLOOD_PRESSURE, HealthDataCategory.VITALS);
1142         sWriteHealthPermissionToHealthDataCategoryMap.put(
1143                 WRITE_BODY_TEMPERATURE, HealthDataCategory.VITALS);
1144         sWriteHealthPermissionToHealthDataCategoryMap.put(
1145                 WRITE_HEART_RATE, HealthDataCategory.VITALS);
1146         sWriteHealthPermissionToHealthDataCategoryMap.put(
1147                 WRITE_HEART_RATE_VARIABILITY, HealthDataCategory.VITALS);
1148         sWriteHealthPermissionToHealthDataCategoryMap.put(
1149                 WRITE_OXYGEN_SATURATION, HealthDataCategory.VITALS);
1150         sWriteHealthPermissionToHealthDataCategoryMap.put(
1151                 WRITE_RESPIRATORY_RATE, HealthDataCategory.VITALS);
1152         sWriteHealthPermissionToHealthDataCategoryMap.put(
1153                 WRITE_RESTING_HEART_RATE, HealthDataCategory.VITALS);
1154 
1155         sDataCategoryToWritePermissionsMap.put(
1156                 HealthDataCategory.ACTIVITY,
1157                 new String[] {
1158                     WRITE_ACTIVE_CALORIES_BURNED,
1159                     WRITE_DISTANCE,
1160                     WRITE_ELEVATION_GAINED,
1161                     WRITE_EXERCISE,
1162                     WRITE_PLANNED_EXERCISE,
1163                     WRITE_FLOORS_CLIMBED,
1164                     WRITE_STEPS,
1165                     WRITE_TOTAL_CALORIES_BURNED,
1166                     WRITE_VO2_MAX,
1167                     WRITE_WHEELCHAIR_PUSHES,
1168                     WRITE_POWER,
1169                     WRITE_SPEED
1170                 });
1171 
1172         sDataCategoryToWritePermissionsMap.put(
1173                 HealthDataCategory.BODY_MEASUREMENTS,
1174                 new String[] {
1175                     WRITE_BASAL_METABOLIC_RATE,
1176                     WRITE_BODY_FAT,
1177                     WRITE_BODY_WATER_MASS,
1178                     WRITE_BONE_MASS,
1179                     WRITE_HEIGHT,
1180                     WRITE_LEAN_BODY_MASS,
1181                     WRITE_WEIGHT
1182                 });
1183 
1184         sDataCategoryToWritePermissionsMap.put(
1185                 HealthDataCategory.CYCLE_TRACKING,
1186                 new String[] {
1187                     WRITE_CERVICAL_MUCUS,
1188                     WRITE_MENSTRUATION,
1189                     WRITE_OVULATION_TEST,
1190                     WRITE_SEXUAL_ACTIVITY,
1191                     WRITE_INTERMENSTRUAL_BLEEDING
1192                 });
1193 
1194         sDataCategoryToWritePermissionsMap.put(
1195                 HealthDataCategory.NUTRITION, new String[] {WRITE_HYDRATION, WRITE_NUTRITION});
1196 
1197         sDataCategoryToWritePermissionsMap.put(
1198                 HealthDataCategory.SLEEP, new String[] {WRITE_SLEEP});
1199 
1200         sDataCategoryToWritePermissionsMap.put(
1201                 HealthDataCategory.VITALS,
1202                 new String[] {
1203                     WRITE_BASAL_BODY_TEMPERATURE,
1204                     WRITE_BLOOD_GLUCOSE,
1205                     WRITE_BLOOD_PRESSURE,
1206                     WRITE_BODY_TEMPERATURE,
1207                     WRITE_HEART_RATE,
1208                     WRITE_HEART_RATE_VARIABILITY,
1209                     WRITE_OXYGEN_SATURATION,
1210                     WRITE_RESPIRATORY_RATE,
1211                     WRITE_RESTING_HEART_RATE
1212                 });
1213 
1214         sDataCategoryToWritePermissionsMap.put(
1215                 HealthDataCategory.WELLNESS, new String[] {WRITE_MINDFULNESS});
1216     }
1217 
1218     private static synchronized void
populateReadMedicalPermissionsToMedicalPermissionCategoryMap()1219             populateReadMedicalPermissionsToMedicalPermissionCategoryMap() {
1220         if (!personalHealthRecord()) {
1221             throw new UnsupportedOperationException(
1222                     "populateReadMedicalPermissionsToMedicalPermissionCategoryMap is not"
1223                             + " supported");
1224         }
1225 
1226         if (!sMedicalCategoryToReadPermissionMap.isEmpty()) {
1227             return;
1228         }
1229         // Populate permission category to read permission map
1230         sMedicalCategoryToReadPermissionMap.put(IMMUNIZATION, READ_MEDICAL_DATA_IMMUNIZATION);
1231     }
1232 }
1233