• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.HealthPermissions.READ_EXERCISE_ROUTE;
20 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_ALLERGIES_INTOLERANCES;
21 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_CONDITIONS;
22 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_LABORATORY_RESULTS;
23 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_MEDICATIONS;
24 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_PERSONAL_DETAILS;
25 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_PRACTITIONER_DETAILS;
26 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_PREGNANCY;
27 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_PROCEDURES;
28 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_SOCIAL_HISTORY;
29 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_VACCINES;
30 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_VISITS;
31 import static android.health.connect.HealthPermissions.READ_MEDICAL_DATA_VITAL_SIGNS;
32 import static android.health.connect.HealthPermissions.WRITE_MEDICAL_DATA;
33 import static android.health.connect.HealthPermissions.isValidHealthPermission;
34 
35 import static com.android.healthfitness.flags.Flags.FLAG_PERSONAL_HEALTH_RECORD;
36 import static com.android.healthfitness.flags.Flags.FLAG_PERSONAL_HEALTH_RECORD_DATABASE;
37 
38 import static com.google.common.truth.Truth.assertThat;
39 import static com.google.common.truth.Truth.assertWithMessage;
40 
41 import static org.mockito.Mockito.reset;
42 
43 import android.content.Context;
44 import android.content.pm.PackageInfo;
45 import android.content.pm.PackageManager;
46 import android.content.pm.PermissionInfo;
47 import android.platform.test.annotations.EnableFlags;
48 import android.platform.test.flag.junit.SetFlagsRule;
49 
50 import androidx.test.InstrumentationRegistry;
51 import androidx.test.ext.junit.runners.AndroidJUnit4;
52 
53 import com.android.healthfitness.flags.Flags;
54 
55 import org.junit.After;
56 import org.junit.Before;
57 import org.junit.Rule;
58 import org.junit.Test;
59 import org.junit.runner.RunWith;
60 import org.mockito.Mock;
61 import org.mockito.MockitoAnnotations;
62 
63 import java.util.Set;
64 import java.util.stream.Collectors;
65 import java.util.stream.Stream;
66 
67 @RunWith(AndroidJUnit4.class)
68 public class HealthPermissionsTest {
69     private static final String FAIL_MESSAGE =
70             "Add new health permission to ALL_EXPECTED_HEALTH_PERMISSIONS and "
71                     + " android.healthconnect.cts.HealthPermissionsPresenceTest.HEALTH_PERMISSIONS "
72                     + "sets.";
73 
74     private static final String PHR_FAIL_MESSAGE =
75             "Add new medical permissions to ALL_EXPECTED_HEALTH_PERMISSIONS and "
76                     + "apk/HealthPermissionsManifest.xml.";
77 
78     private static final String MEDICAL_PERMISSION_IDENTIFIER = "MEDICAL_DATA";
79 
80     // Add new health permission to ALL_EXPECTED_HEALTH_PERMISSIONS and
81     // {@link android.healthconnect.cts.HealthPermissionsPresenceTest.HEALTH_PERMISSIONS}
82     // sets.
83     private static final Set<String> ALL_EXPECTED_HEALTH_PERMISSIONS =
84             Stream.concat(
85                             Stream.of(
86                                     HealthPermissions.READ_HEALTH_DATA_HISTORY,
87                                     HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND,
88                                     HealthPermissions.READ_ACTIVE_CALORIES_BURNED,
89                                     HealthPermissions.READ_DISTANCE,
90                                     HealthPermissions.READ_ELEVATION_GAINED,
91                                     HealthPermissions.READ_EXERCISE,
92                                     HealthPermissions.READ_EXERCISE_ROUTES,
93                                     HealthPermissions.READ_PLANNED_EXERCISE,
94                                     HealthPermissions.READ_FLOORS_CLIMBED,
95                                     HealthPermissions.READ_STEPS,
96                                     HealthPermissions.READ_TOTAL_CALORIES_BURNED,
97                                     HealthPermissions.READ_VO2_MAX,
98                                     HealthPermissions.READ_WHEELCHAIR_PUSHES,
99                                     HealthPermissions.READ_POWER,
100                                     HealthPermissions.READ_SPEED,
101                                     HealthPermissions.READ_BASAL_METABOLIC_RATE,
102                                     HealthPermissions.READ_BODY_FAT,
103                                     HealthPermissions.READ_BODY_WATER_MASS,
104                                     HealthPermissions.READ_BONE_MASS,
105                                     HealthPermissions.READ_HEIGHT,
106                                     HealthPermissions.READ_LEAN_BODY_MASS,
107                                     HealthPermissions.READ_WEIGHT,
108                                     HealthPermissions.READ_CERVICAL_MUCUS,
109                                     HealthPermissions.READ_INTERMENSTRUAL_BLEEDING,
110                                     HealthPermissions.READ_MENSTRUATION,
111                                     HealthPermissions.READ_OVULATION_TEST,
112                                     HealthPermissions.READ_SEXUAL_ACTIVITY,
113                                     HealthPermissions.READ_HYDRATION,
114                                     HealthPermissions.READ_NUTRITION,
115                                     HealthPermissions.READ_SLEEP,
116                                     HealthPermissions.READ_BASAL_BODY_TEMPERATURE,
117                                     HealthPermissions.READ_BLOOD_GLUCOSE,
118                                     HealthPermissions.READ_BLOOD_PRESSURE,
119                                     HealthPermissions.READ_BODY_TEMPERATURE,
120                                     HealthPermissions.READ_HEART_RATE,
121                                     HealthPermissions.READ_HEART_RATE_VARIABILITY,
122                                     HealthPermissions.READ_OXYGEN_SATURATION,
123                                     HealthPermissions.READ_RESPIRATORY_RATE,
124                                     HealthPermissions.READ_RESTING_HEART_RATE,
125                                     HealthPermissions.READ_SKIN_TEMPERATURE,
126                                     HealthPermissions.READ_MINDFULNESS,
127                                     HealthPermissions.READ_MEDICAL_DATA_ALLERGIES_INTOLERANCES,
128                                     HealthPermissions.READ_MEDICAL_DATA_CONDITIONS,
129                                     HealthPermissions.READ_MEDICAL_DATA_LABORATORY_RESULTS,
130                                     HealthPermissions.READ_MEDICAL_DATA_MEDICATIONS,
131                                     HealthPermissions.READ_MEDICAL_DATA_PERSONAL_DETAILS,
132                                     HealthPermissions.READ_MEDICAL_DATA_PRACTITIONER_DETAILS,
133                                     HealthPermissions.READ_MEDICAL_DATA_PREGNANCY,
134                                     HealthPermissions.READ_MEDICAL_DATA_PROCEDURES,
135                                     HealthPermissions.READ_MEDICAL_DATA_SOCIAL_HISTORY,
136                                     HealthPermissions.READ_MEDICAL_DATA_VACCINES,
137                                     HealthPermissions.READ_MEDICAL_DATA_VISITS,
138                                     HealthPermissions.READ_MEDICAL_DATA_VITAL_SIGNS,
139                                     HealthPermissions.WRITE_ACTIVE_CALORIES_BURNED,
140                                     HealthPermissions.WRITE_DISTANCE,
141                                     HealthPermissions.WRITE_ELEVATION_GAINED,
142                                     HealthPermissions.WRITE_EXERCISE,
143                                     HealthPermissions.WRITE_EXERCISE_ROUTE,
144                                     HealthPermissions.WRITE_PLANNED_EXERCISE,
145                                     HealthPermissions.WRITE_FLOORS_CLIMBED,
146                                     HealthPermissions.WRITE_STEPS,
147                                     HealthPermissions.WRITE_TOTAL_CALORIES_BURNED,
148                                     HealthPermissions.WRITE_VO2_MAX,
149                                     HealthPermissions.WRITE_WHEELCHAIR_PUSHES,
150                                     HealthPermissions.WRITE_POWER,
151                                     HealthPermissions.WRITE_SPEED,
152                                     HealthPermissions.WRITE_BASAL_METABOLIC_RATE,
153                                     HealthPermissions.WRITE_BODY_FAT,
154                                     HealthPermissions.WRITE_BODY_WATER_MASS,
155                                     HealthPermissions.WRITE_BONE_MASS,
156                                     HealthPermissions.WRITE_HEIGHT,
157                                     HealthPermissions.WRITE_LEAN_BODY_MASS,
158                                     HealthPermissions.WRITE_WEIGHT,
159                                     HealthPermissions.WRITE_CERVICAL_MUCUS,
160                                     HealthPermissions.WRITE_INTERMENSTRUAL_BLEEDING,
161                                     HealthPermissions.WRITE_MENSTRUATION,
162                                     HealthPermissions.WRITE_OVULATION_TEST,
163                                     HealthPermissions.WRITE_SEXUAL_ACTIVITY,
164                                     HealthPermissions.WRITE_HYDRATION,
165                                     HealthPermissions.WRITE_NUTRITION,
166                                     HealthPermissions.WRITE_SLEEP,
167                                     HealthPermissions.WRITE_BASAL_BODY_TEMPERATURE,
168                                     HealthPermissions.WRITE_BLOOD_GLUCOSE,
169                                     HealthPermissions.WRITE_BLOOD_PRESSURE,
170                                     HealthPermissions.WRITE_BODY_TEMPERATURE,
171                                     HealthPermissions.WRITE_HEART_RATE,
172                                     HealthPermissions.WRITE_HEART_RATE_VARIABILITY,
173                                     HealthPermissions.WRITE_OXYGEN_SATURATION,
174                                     HealthPermissions.WRITE_RESPIRATORY_RATE,
175                                     HealthPermissions.WRITE_RESTING_HEART_RATE,
176                                     HealthPermissions.WRITE_SKIN_TEMPERATURE,
177                                     HealthPermissions.WRITE_MINDFULNESS,
178                                     HealthPermissions.WRITE_MEDICAL_DATA),
179                             Flags.activityIntensity()
180                                     ? Stream.of(
181                                             HealthPermissions.READ_ACTIVITY_INTENSITY,
182                                             HealthPermissions.WRITE_ACTIVITY_INTENSITY)
183                                     : Stream.of())
184                     .collect(Collectors.toSet());
185     private PackageManager mPackageManager;
186     private Context mContext;
187     @Mock private PackageInfo mPackageInfo1;
188 
189     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
190 
191     @Before
setUp()192     public void setUp() {
193         MockitoAnnotations.initMocks(this);
194         mContext = InstrumentationRegistry.getTargetContext();
195         mPackageManager = mContext.getPackageManager();
196     }
197 
198     @After
tearDown()199     public void tearDown() {
200         reset(mPackageInfo1);
201     }
202 
203     @Test
testHealthGroupPermissions_noUnexpectedPermissionsDefined()204     public void testHealthGroupPermissions_noUnexpectedPermissionsDefined() throws Exception {
205         PermissionInfo[] permissionInfos = getHealthPermissionInfos();
206         for (PermissionInfo permissionInfo : permissionInfos) {
207             if (isValidHealthPermission(permissionInfo)) {
208                 assertWithMessage(FAIL_MESSAGE)
209                         .that(ALL_EXPECTED_HEALTH_PERMISSIONS)
210                         .contains(permissionInfo.name);
211             }
212         }
213     }
214 
215     @Test
testHealthConnectManager_noUnexpectedPermissionsReturned()216     public void testHealthConnectManager_noUnexpectedPermissionsReturned() throws Exception {
217         assertWithMessage(FAIL_MESSAGE)
218                 .that(HealthConnectManager.getHealthPermissions(mContext))
219                 .isEqualTo(ALL_EXPECTED_HEALTH_PERMISSIONS);
220     }
221 
222     @Test
testReadExerciseRoutePerm_hasSignatureProtection()223     public void testReadExerciseRoutePerm_hasSignatureProtection() throws Exception {
224         assertThat(
225                         mPackageManager
226                                 .getPermissionInfo(READ_EXERCISE_ROUTE, /* flags= */ 0)
227                                 .getProtection())
228                 .isEqualTo(PermissionInfo.PROTECTION_SIGNATURE);
229     }
230 
231     @Test
testReadExerciseRoutePerm_controllerUiHoldsIt()232     public void testReadExerciseRoutePerm_controllerUiHoldsIt() throws Exception {
233         String healthControllerPackageName = getControllerUiPackageName();
234         assertThat(
235                         mContext.getPackageManager()
236                                 .checkPermission(READ_EXERCISE_ROUTE, healthControllerPackageName))
237                 .isEqualTo(PackageManager.PERMISSION_GRANTED);
238     }
239 
240     @Test
testGetDataCategoriesWithWritePermissionsForPackage_returnsCorrectSet()241     public void testGetDataCategoriesWithWritePermissionsForPackage_returnsCorrectSet() {
242         mPackageInfo1.requestedPermissions =
243                 new String[] {
244                     HealthPermissions.WRITE_STEPS,
245                     HealthPermissions.WRITE_SLEEP,
246                     HealthPermissions.READ_HEART_RATE,
247                     HealthPermissions.WRITE_OVULATION_TEST
248                 };
249         mPackageInfo1.requestedPermissionsFlags =
250                 new int[] {
251                     PackageInfo.REQUESTED_PERMISSION_GRANTED,
252                     0,
253                     PackageInfo.REQUESTED_PERMISSION_GRANTED,
254                     PackageInfo.REQUESTED_PERMISSION_GRANTED
255                 };
256 
257         Set<Integer> expectedResult =
258                 Set.of(HealthDataCategory.ACTIVITY, HealthDataCategory.CYCLE_TRACKING);
259         Set<Integer> actualResult =
260                 HealthPermissions.getDataCategoriesWithWritePermissionsForPackage(
261                         mPackageInfo1, mContext);
262         assertThat(actualResult).isEqualTo(expectedResult);
263     }
264 
265     @Test
266     public void
testPackageHasWriteHealthPermissionsForCategory_ifNoWritePermissions_returnsFalse()267             testPackageHasWriteHealthPermissionsForCategory_ifNoWritePermissions_returnsFalse() {
268         mPackageInfo1.requestedPermissions =
269                 new String[] {
270                     HealthPermissions.WRITE_EXERCISE,
271                     HealthPermissions.WRITE_SLEEP,
272                     HealthPermissions.READ_HEART_RATE,
273                     HealthPermissions.WRITE_OVULATION_TEST
274                 };
275         mPackageInfo1.requestedPermissionsFlags =
276                 new int[] {
277                     PackageInfo.REQUESTED_PERMISSION_GRANTED,
278                     0,
279                     PackageInfo.REQUESTED_PERMISSION_GRANTED,
280                     PackageInfo.REQUESTED_PERMISSION_GRANTED
281                 };
282 
283         assertThat(
284                         HealthPermissions.getPackageHasWriteHealthPermissionsForCategory(
285                                 mPackageInfo1, HealthDataCategory.SLEEP, mContext))
286                 .isFalse();
287     }
288 
289     @Test
testPackageHasWriteHealthPermissionsForCategory_ifWritePermissions_returnsTrue()290     public void testPackageHasWriteHealthPermissionsForCategory_ifWritePermissions_returnsTrue() {
291         mPackageInfo1.requestedPermissions =
292                 new String[] {
293                     HealthPermissions.WRITE_STEPS,
294                     HealthPermissions.WRITE_SLEEP,
295                     HealthPermissions.READ_HEART_RATE,
296                     HealthPermissions.WRITE_OVULATION_TEST
297                 };
298         mPackageInfo1.requestedPermissionsFlags =
299                 new int[] {
300                     PackageInfo.REQUESTED_PERMISSION_GRANTED,
301                     0,
302                     PackageInfo.REQUESTED_PERMISSION_GRANTED,
303                     PackageInfo.REQUESTED_PERMISSION_GRANTED
304                 };
305 
306         assertThat(
307                         HealthPermissions.getPackageHasWriteHealthPermissionsForCategory(
308                                 mPackageInfo1, HealthDataCategory.ACTIVITY, mContext))
309                 .isTrue();
310     }
311 
312     @Test
313     @EnableFlags({FLAG_PERSONAL_HEALTH_RECORD, FLAG_PERSONAL_HEALTH_RECORD_DATABASE})
testGetMedicalPermissions_returnsValidPermissions()314     public void testGetMedicalPermissions_returnsValidPermissions() {
315         Set<String> permissions = HealthPermissions.getAllMedicalPermissions();
316         assertThat(permissions)
317                 .containsAtLeast(
318                         WRITE_MEDICAL_DATA,
319                         READ_MEDICAL_DATA_ALLERGIES_INTOLERANCES,
320                         READ_MEDICAL_DATA_CONDITIONS,
321                         READ_MEDICAL_DATA_LABORATORY_RESULTS,
322                         READ_MEDICAL_DATA_MEDICATIONS,
323                         READ_MEDICAL_DATA_PERSONAL_DETAILS,
324                         READ_MEDICAL_DATA_PRACTITIONER_DETAILS,
325                         READ_MEDICAL_DATA_PREGNANCY,
326                         READ_MEDICAL_DATA_PROCEDURES,
327                         READ_MEDICAL_DATA_SOCIAL_HISTORY,
328                         READ_MEDICAL_DATA_VACCINES,
329                         READ_MEDICAL_DATA_VISITS,
330                         READ_MEDICAL_DATA_VITAL_SIGNS);
331     }
332 
333     @Test
334     @EnableFlags({FLAG_PERSONAL_HEALTH_RECORD, FLAG_PERSONAL_HEALTH_RECORD_DATABASE})
testGetMedicalPermissions_returnsAllMedicalPermissions()335     public void testGetMedicalPermissions_returnsAllMedicalPermissions() throws Exception {
336         Set<String> permissions = HealthPermissions.getAllMedicalPermissions();
337 
338         PermissionInfo[] permissionInfos = getHealthPermissionInfos();
339         for (PermissionInfo permissionInfo : permissionInfos) {
340             if (isValidHealthPermission(permissionInfo)
341                     && permissionInfo.name.contains(MEDICAL_PERMISSION_IDENTIFIER)) {
342                 assertWithMessage(PHR_FAIL_MESSAGE).that(permissions).contains(permissionInfo.name);
343             }
344         }
345     }
346 
getHealthPermissionInfos()347     private PermissionInfo[] getHealthPermissionInfos() throws Exception {
348         String healthControllerPackageName = getControllerUiPackageName();
349 
350         PackageInfo packageInfo =
351                 mPackageManager.getPackageInfo(
352                         healthControllerPackageName,
353                         PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS));
354         return packageInfo.permissions;
355     }
356 
getControllerUiPackageName()357     private String getControllerUiPackageName() throws Exception {
358         return mPackageManager.getPermissionInfo(HealthPermissions.READ_STEPS, /* flags= */ 0)
359                 .packageName;
360     }
361 }
362