• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 com.android.server.healthconnect.permission;
18 
19 import static android.health.connect.HealthPermissions.WRITE_MEDICAL_DATA;
20 import static android.health.connect.internal.datatypes.utils.MedicalResourceTypePermissionMapper.getMedicalReadPermission;
21 import static android.permission.PermissionManager.PERMISSION_GRANTED;
22 
23 import android.content.AttributionSource;
24 import android.health.connect.HealthPermissions;
25 import android.health.connect.datatypes.MedicalResource;
26 import android.permission.PermissionManager;
27 import android.util.ArraySet;
28 
29 import java.util.Set;
30 
31 /**
32  * Helper class to force caller of medical data apis to hold api required permissions.
33  *
34  * @hide
35  */
36 public class MedicalDataPermissionEnforcer {
37     private final PermissionManager mPermissionManager;
38 
MedicalDataPermissionEnforcer(PermissionManager permissionManager)39     public MedicalDataPermissionEnforcer(PermissionManager permissionManager) {
40         mPermissionManager = permissionManager;
41     }
42 
43     /**
44      * Enforces that caller has write permission for medical data.
45      *
46      * @throws SecurityException if the app does not have write permission.
47      */
enforceWriteMedicalDataPermission(AttributionSource attributionSource)48     public void enforceWriteMedicalDataPermission(AttributionSource attributionSource) {
49         if (!isPermissionGranted(WRITE_MEDICAL_DATA, attributionSource)) {
50             throw new SecurityException(
51                     "Caller doesn't have " + WRITE_MEDICAL_DATA + " to write MedicalResource");
52         }
53     }
54 
55     /**
56      * Enforces that caller has either read or write permissions for given medicalResourceType.
57      * Returns {@code true} if the caller is allowed to read only records written by itself, false
58      * if the caller is allowed to read records written by any apps including itself.
59      *
60      * @throws SecurityException if the app has neither read nor write permissions for any of the
61      *     specified medical resources.
62      */
enforceMedicalReadAccessAndGetEnforceSelfRead( @edicalResource.MedicalResourceType int medicalResourceType, AttributionSource attributionSource)63     public boolean enforceMedicalReadAccessAndGetEnforceSelfRead(
64             @MedicalResource.MedicalResourceType int medicalResourceType,
65             AttributionSource attributionSource) {
66         String readPermissionName = getMedicalReadPermission(medicalResourceType);
67 
68         if (isPermissionGranted(readPermissionName, attributionSource)) {
69             return false;
70         }
71 
72         if (isPermissionGranted(WRITE_MEDICAL_DATA, attributionSource)) {
73             // Apps are always allowed to read self data if they have insert permission.
74             return true;
75         }
76         throw new SecurityException(
77                 "Caller doesn't have " + readPermissionName + " to read MedicalResource");
78     }
79 
80     /**
81      * Returns a list of read or write medical permissions the caller has been granted permission to
82      * access. Uses checkPermissionForPreflight as this method is not used for delivering data but
83      * checking permission state.
84      */
getGrantedMedicalPermissionsForPreflight( AttributionSource attributionSource)85     public Set<String> getGrantedMedicalPermissionsForPreflight(
86             AttributionSource attributionSource) {
87         Set<String> grantedPermissions = new ArraySet<>();
88 
89         for (String permission : HealthPermissions.getAllMedicalPermissions()) {
90             if (mPermissionManager.checkPermissionForPreflight(permission, attributionSource)
91                     == PERMISSION_GRANTED) {
92                 grantedPermissions.add(permission);
93             }
94         }
95         return grantedPermissions;
96     }
97 
isPermissionGranted( String permissionName, AttributionSource attributionSource)98     private boolean isPermissionGranted(
99             String permissionName, AttributionSource attributionSource) {
100         return mPermissionManager.checkPermissionForDataDelivery(
101                         permissionName, attributionSource, null)
102                 == PERMISSION_GRANTED;
103     }
104 }
105