1 /* 2 * Copyright 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 * https://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 */ 18 19 package com.android.healthconnect.controller.permissions.additionalaccess 20 21 import android.content.pm.PackageManager 22 import android.health.connect.HealthPermissions.READ_EXERCISE 23 import android.health.connect.HealthPermissions.READ_EXERCISE_ROUTES 24 import com.android.healthconnect.controller.permissions.api.GetHealthPermissionsFlagsUseCase 25 import com.android.healthconnect.controller.permissions.api.IGetGrantedHealthPermissionsUseCase 26 import com.android.healthconnect.controller.service.IoDispatcher 27 import com.android.healthconnect.controller.shared.usecase.BaseUseCase 28 import com.android.healthconnect.controller.shared.usecase.UseCaseResults 29 import javax.inject.Inject 30 import javax.inject.Singleton 31 import kotlinx.coroutines.CoroutineDispatcher 32 33 @Singleton 34 class LoadExerciseRoutePermissionUseCase 35 @Inject 36 constructor( 37 private val loadDeclaredHealthPermissionUseCase: LoadDeclaredHealthPermissionUseCase, 38 private val getHealthPermissionsFlagsUseCase: GetHealthPermissionsFlagsUseCase, 39 private val getGrantedHealthPermissionsUseCase: IGetGrantedHealthPermissionsUseCase, 40 @IoDispatcher dispatcher: CoroutineDispatcher 41 ) : BaseUseCase<String, ExerciseRouteState>(dispatcher), ILoadExerciseRoutePermissionUseCase { 42 executenull43 override suspend fun execute(input: String): ExerciseRouteState { 44 val grantedPermissions = getGrantedHealthPermissionsUseCase(input) 45 val appPermissions = loadDeclaredHealthPermissionUseCase(input) 46 val permissionFlags = 47 getHealthPermissionsFlagsUseCase(input, listOf(READ_EXERCISE_ROUTES, READ_EXERCISE)) 48 return ExerciseRouteState( 49 exerciseRoutePermissionState = 50 getPermissionState( 51 READ_EXERCISE_ROUTES, grantedPermissions, appPermissions, permissionFlags), 52 exercisePermissionState = 53 getPermissionState( 54 READ_EXERCISE, grantedPermissions, appPermissions, permissionFlags)) 55 } 56 getPermissionStatenull57 private fun getPermissionState( 58 permission: String, 59 grantedPermissions: List<String>, 60 appPermissions: List<String>, 61 permissionFlags: Map<String, Int> 62 ): PermissionUiState { 63 64 if (grantedPermissions.contains(permission)) { 65 return PermissionUiState.ALWAYS_ALLOW 66 } 67 68 if (!appPermissions.contains(permission)) { 69 return PermissionUiState.NOT_DECLARED 70 } 71 72 val flag = permissionFlags[permission] ?: return PermissionUiState.NOT_DECLARED 73 if (flag.and(PackageManager.FLAG_PERMISSION_USER_FIXED) != 0) { 74 return PermissionUiState.NEVER_ALLOW 75 } 76 77 return PermissionUiState.ASK_EVERY_TIME 78 } 79 } 80 81 data class ExerciseRouteState( 82 val exerciseRoutePermissionState: PermissionUiState, 83 val exercisePermissionState: PermissionUiState 84 ) 85 86 enum class PermissionUiState { 87 NOT_DECLARED, 88 ASK_EVERY_TIME, 89 ALWAYS_ALLOW, 90 NEVER_ALLOW 91 } 92 93 interface ILoadExerciseRoutePermissionUseCase { invokenull94 suspend operator fun invoke(input: String): UseCaseResults<ExerciseRouteState> 95 96 suspend fun execute(input: String): ExerciseRouteState 97 } 98