/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.health.connect.client.permission
import androidx.annotation.RestrictTo
import androidx.health.connect.client.records.ActiveCaloriesBurnedRecord
import androidx.health.connect.client.records.BasalBodyTemperatureRecord
import androidx.health.connect.client.records.BasalMetabolicRateRecord
import androidx.health.connect.client.records.BloodGlucoseRecord
import androidx.health.connect.client.records.BloodPressureRecord
import androidx.health.connect.client.records.BodyFatRecord
import androidx.health.connect.client.records.BodyTemperatureRecord
import androidx.health.connect.client.records.BodyWaterMassRecord
import androidx.health.connect.client.records.BoneMassRecord
import androidx.health.connect.client.records.CervicalMucusRecord
import androidx.health.connect.client.records.CyclingPedalingCadenceRecord
import androidx.health.connect.client.records.DistanceRecord
import androidx.health.connect.client.records.ElevationGainedRecord
import androidx.health.connect.client.records.ExerciseSessionRecord
import androidx.health.connect.client.records.FloorsClimbedRecord
import androidx.health.connect.client.records.HeartRateRecord
import androidx.health.connect.client.records.HeartRateVariabilityRmssdRecord
import androidx.health.connect.client.records.HeightRecord
import androidx.health.connect.client.records.HydrationRecord
import androidx.health.connect.client.records.IntermenstrualBleedingRecord
import androidx.health.connect.client.records.LeanBodyMassRecord
import androidx.health.connect.client.records.MenstruationFlowRecord
import androidx.health.connect.client.records.MenstruationPeriodRecord
import androidx.health.connect.client.records.NutritionRecord
import androidx.health.connect.client.records.OvulationTestRecord
import androidx.health.connect.client.records.OxygenSaturationRecord
import androidx.health.connect.client.records.PowerRecord
import androidx.health.connect.client.records.Record
import androidx.health.connect.client.records.RespiratoryRateRecord
import androidx.health.connect.client.records.RestingHeartRateRecord
import androidx.health.connect.client.records.SexualActivityRecord
import androidx.health.connect.client.records.SleepSessionRecord
import androidx.health.connect.client.records.SleepStageRecord
import androidx.health.connect.client.records.SpeedRecord
import androidx.health.connect.client.records.StepsCadenceRecord
import androidx.health.connect.client.records.StepsRecord
import androidx.health.connect.client.records.TotalCaloriesBurnedRecord
import androidx.health.connect.client.records.Vo2MaxRecord
import androidx.health.connect.client.records.WeightRecord
import androidx.health.connect.client.records.WheelchairPushesRecord
import kotlin.reflect.KClass
/**
* A Permission either to read or write data associated with a [Record] type.
*
* @see androidx.health.connect.client.PermissionController
*/
public class HealthPermission
internal constructor(
/** type of [Record] the permission gives access for. */
internal val recordType: KClass<out Record>,
/** whether read or write access. */
@property:AccessType internal val accessType: Int,
) {
companion object {
/**
* Creates [HealthPermission] to read provided [recordType], such as `Steps::class`.
*
* @return Permission object to use with
* [androidx.health.connect.client.PermissionController].
*/
@RestrictTo(RestrictTo.Scope.LIBRARY) // To be deleted.
@JvmStatic
public fun createReadPermissionLegacy(recordType: KClass<out Record>): HealthPermission {
return HealthPermission(recordType, AccessTypes.READ)
}
/**
* Returns a permission defined in [HealthPermission] to read provided [recordType], such as
* `Steps::class`.
*
* @return Permission to use with [androidx.health.connect.client.PermissionController].
* @throws IllegalArgumentException if the given record type is invalid.
*/
@JvmStatic
public fun getReadPermission(recordType: KClass<out Record>): String {
if (RECORD_TYPE_TO_PERMISSION[recordType] == null) {
throw IllegalArgumentException(
"Given recordType is not valid : $recordType.simpleName"
)
}
return READ_PERMISSION_PREFIX + RECORD_TYPE_TO_PERMISSION[recordType]
}
/**
* Creates [HealthPermission] to write provided [recordType], such as `Steps::class`.
*
* @return Permission to use with [androidx.health.connect.client.PermissionController].
*/
@RestrictTo(RestrictTo.Scope.LIBRARY) // To be deleted.
@JvmStatic
public fun createWritePermissionLegacy(recordType: KClass<out Record>): HealthPermission {
return HealthPermission(recordType, AccessTypes.WRITE)
}
/**
* Returns a permission defined in [HealthPermission] to read provided [recordType], such as
* `Steps::class`.
*
* @return Permission object to use with
* [androidx.health.connect.client.PermissionController].
* @throws IllegalArgumentException if the given record type is invalid.
*/
@JvmStatic
public fun getWritePermission(recordType: KClass<out Record>): String {
if (RECORD_TYPE_TO_PERMISSION[recordType] == null) {
throw IllegalArgumentException(
"Given recordType is not valid : $recordType.simpleName"
)
}
return WRITE_PERMISSION_PREFIX + RECORD_TYPE_TO_PERMISSION.getOrDefault(recordType, "")
}
// Read permissions for ACTIVITY.
internal const val READ_ACTIVE_CALORIES_BURNED =
"android.permission.health.READ_ACTIVE_CALORIES_BURNED"
internal const val READ_DISTANCE = "android.permission.health.READ_DISTANCE"
internal const val READ_ELEVATION_GAINED = "android.permission.health.READ_ELEVATION_GAINED"
internal const val READ_EXERCISE = "android.permission.health.READ_EXERCISE"
internal const val READ_FLOORS_CLIMBED = "android.permission.health.READ_FLOORS_CLIMBED"
internal const val READ_STEPS = "android.permission.health.READ_STEPS"
internal const val READ_TOTAL_CALORIES_BURNED =
"android.permission.health.READ_TOTAL_CALORIES_BURNED"
internal const val READ_VO2_MAX = "android.permission.health.READ_VO2_MAX"
internal const val READ_WHEELCHAIR_PUSHES =
"android.permission.health.READ_WHEELCHAIR_PUSHES"
internal const val READ_POWER = "android.permission.health.READ_POWER"
internal const val READ_SPEED = "android.permission.health.READ_SPEED"
// Read permissions for BODY_MEASUREMENTS.
internal const val READ_BASAL_METABOLIC_RATE =
"android.permission.health.READ_BASAL_METABOLIC_RATE"
internal const val READ_BODY_FAT = "android.permission.health.READ_BODY_FAT"
internal const val READ_BODY_WATER_MASS = "android.permission.health.READ_BODY_WATER_MASS"
internal const val READ_BONE_MASS = "android.permission.health.READ_BONE_MASS"
internal const val READ_HEIGHT = "android.permission.health.READ_HEIGHT"
@RestrictTo(RestrictTo.Scope.LIBRARY)
internal const val READ_HIP_CIRCUMFERENCE =
"android.permission.health.READ_HIP_CIRCUMFERENCE"
internal const val READ_LEAN_BODY_MASS = "android.permission.health.READ_LEAN_BODY_MASS"
@RestrictTo(RestrictTo.Scope.LIBRARY)
internal const val READ_WAIST_CIRCUMFERENCE =
"android.permission.health.READ_WAIST_CIRCUMFERENCE"
internal const val READ_WEIGHT = "android.permission.health.READ_WEIGHT"
// Read permissions for CYCLE_TRACKING.
internal const val READ_CERVICAL_MUCUS = "android.permission.health.READ_CERVICAL_MUCUS"
@RestrictTo(RestrictTo.Scope.LIBRARY)
internal const val READ_INTERMENSTRUAL_BLEEDING =
"android.permission.health.READ_INTERMENSTRUAL_BLEEDING"
internal const val READ_MENSTRUATION = "android.permission.health.READ_MENSTRUATION"
internal const val READ_OVULATION_TEST = "android.permission.health.READ_OVULATION_TEST"
internal const val READ_SEXUAL_ACTIVITY = "android.permission.health.READ_SEXUAL_ACTIVITY"
// Read permissions for NUTRITION.
internal const val READ_HYDRATION = "android.permission.health.READ_HYDRATION"
internal const val READ_NUTRITION = "android.permission.health.READ_NUTRITION"
// Read permissions for SLEEP.
internal const val READ_SLEEP = "android.permission.health.READ_SLEEP"
// Read permissions for VITALS.
internal const val READ_BASAL_BODY_TEMPERATURE =
"android.permission.health.READ_BASAL_BODY_TEMPERATURE"
internal const val READ_BLOOD_GLUCOSE = "android.permission.health.READ_BLOOD_GLUCOSE"
internal const val READ_BLOOD_PRESSURE = "android.permission.health.READ_BLOOD_PRESSURE"
internal const val READ_BODY_TEMPERATURE = "android.permission.health.READ_BODY_TEMPERATURE"
internal const val READ_HEART_RATE = "android.permission.health.READ_HEART_RATE"
internal const val READ_HEART_RATE_VARIABILITY =
"android.permission.health.READ_HEART_RATE_VARIABILITY"
internal const val READ_OXYGEN_SATURATION =
"android.permission.health.READ_OXYGEN_SATURATION"
internal const val READ_RESPIRATORY_RATE = "android.permission.health.READ_RESPIRATORY_RATE"
internal const val READ_RESTING_HEART_RATE =
"android.permission.health.READ_RESTING_HEART_RATE"
// Write permissions for ACTIVITY.
internal const val WRITE_ACTIVE_CALORIES_BURNED =
"android.permission.health.WRITE_ACTIVE_CALORIES_BURNED"
internal const val WRITE_DISTANCE = "android.permission.health.WRITE_DISTANCE"
internal const val WRITE_ELEVATION_GAINED =
"android.permission.health.WRITE_ELEVATION_GAINED"
internal const val WRITE_EXERCISE = "android.permission.health.WRITE_EXERCISE"
internal const val WRITE_FLOORS_CLIMBED = "android.permission.health.WRITE_FLOORS_CLIMBED"
internal const val WRITE_STEPS = "android.permission.health.WRITE_STEPS"
internal const val WRITE_TOTAL_CALORIES_BURNED =
"android.permission.health.WRITE_TOTAL_CALORIES_BURNED"
internal const val WRITE_VO2_MAX = "android.permission.health.WRITE_VO2_MAX"
internal const val WRITE_WHEELCHAIR_PUSHES =
"android.permission.health.WRITE_WHEELCHAIR_PUSHES"
internal const val WRITE_POWER = "android.permission.health.WRITE_POWER"
internal const val WRITE_SPEED = "android.permission.health.WRITE_SPEED"
// Write permissions for BODY_MEASUREMENTS.
internal const val WRITE_BASAL_METABOLIC_RATE =
"android.permission.health.WRITE_BASAL_METABOLIC_RATE"
internal const val WRITE_BODY_FAT = "android.permission.health.WRITE_BODY_FAT"
internal const val WRITE_BODY_WATER_MASS = "android.permission.health.WRITE_BODY_WATER_MASS"
internal const val WRITE_BONE_MASS = "android.permission.health.WRITE_BONE_MASS"
internal const val WRITE_HEIGHT = "android.permission.health.WRITE_HEIGHT"
@RestrictTo(RestrictTo.Scope.LIBRARY)
internal const val WRITE_HIP_CIRCUMFERENCE =
"android.permission.health.WRITE_HIP_CIRCUMFERENCE"
internal const val WRITE_LEAN_BODY_MASS = "android.permission.health.WRITE_LEAN_BODY_MASS"
@RestrictTo(RestrictTo.Scope.LIBRARY)
internal const val WRITE_WAIST_CIRCUMFERENCE =
"android.permission.health.WRITE_WAIST_CIRCUMFERENCE"
internal const val WRITE_WEIGHT = "android.permission.health.WRITE_WEIGHT"
// Write permissions for CYCLE_TRACKING.
internal const val WRITE_CERVICAL_MUCUS = "android.permission.health.WRITE_CERVICAL_MUCUS"
@RestrictTo(RestrictTo.Scope.LIBRARY)
internal const val WRITE_INTERMENSTRUAL_BLEEDING =
"android.permission.health.WRITE_INTERMENSTRUAL_BLEEDING"
internal const val WRITE_MENSTRUATION = "android.permission.health.WRITE_MENSTRUATION"
internal const val WRITE_OVULATION_TEST = "android.permission.health.WRITE_OVULATION_TEST"
internal const val WRITE_SEXUAL_ACTIVITY = "android.permission.health.WRITE_SEXUAL_ACTIVITY"
// Write permissions for NUTRITION.
internal const val WRITE_HYDRATION = "android.permission.health.WRITE_HYDRATION"
internal const val WRITE_NUTRITION = "android.permission.health.WRITE_NUTRITION"
// Write permissions for SLEEP.
internal const val WRITE_SLEEP = "android.permission.health.WRITE_SLEEP"
// Write permissions for VITALS.
internal const val WRITE_BASAL_BODY_TEMPERATURE =
"android.permission.health.WRITE_BASAL_BODY_TEMPERATURE"
internal const val WRITE_BLOOD_GLUCOSE = "android.permission.health.WRITE_BLOOD_GLUCOSE"
internal const val WRITE_BLOOD_PRESSURE = "android.permission.health.WRITE_BLOOD_PRESSURE"
internal const val WRITE_BODY_TEMPERATURE =
"android.permission.health.WRITE_BODY_TEMPERATURE"
internal const val WRITE_HEART_RATE = "android.permission.health.WRITE_HEART_RATE"
internal const val WRITE_HEART_RATE_VARIABILITY =
"android.permission.health.WRITE_HEART_RATE_VARIABILITY"
internal const val WRITE_OXYGEN_SATURATION =
"android.permission.health.WRITE_OXYGEN_SATURATION"
internal const val WRITE_RESPIRATORY_RATE =
"android.permission.health.WRITE_RESPIRATORY_RATE"
internal const val WRITE_RESTING_HEART_RATE =
"android.permission.health.WRITE_RESTING_HEART_RATE"
internal const val READ_PERMISSION_PREFIX = "android.permission.health.READ_"
internal const val WRITE_PERMISSION_PREFIX = "android.permission.health.WRITE_"
internal val RECORD_TYPE_TO_PERMISSION =
mapOf<KClass<out Record>, String>(
ActiveCaloriesBurnedRecord::class to
READ_ACTIVE_CALORIES_BURNED.substringAfter(READ_PERMISSION_PREFIX),
BasalBodyTemperatureRecord::class to
READ_BASAL_BODY_TEMPERATURE.substringAfter(READ_PERMISSION_PREFIX),
BasalMetabolicRateRecord::class to
READ_BASAL_METABOLIC_RATE.substringAfter(READ_PERMISSION_PREFIX),
BloodGlucoseRecord::class to
READ_BLOOD_GLUCOSE.substringAfter(READ_PERMISSION_PREFIX),
BloodPressureRecord::class to
READ_BLOOD_PRESSURE.substringAfter(READ_PERMISSION_PREFIX),
BodyFatRecord::class to READ_BODY_FAT.substringAfter(READ_PERMISSION_PREFIX),
BodyTemperatureRecord::class to
READ_BODY_TEMPERATURE.substringAfter(READ_PERMISSION_PREFIX),
BodyWaterMassRecord::class to
READ_BODY_WATER_MASS.substringAfter(READ_PERMISSION_PREFIX),
BoneMassRecord::class to READ_BONE_MASS.substringAfter(READ_PERMISSION_PREFIX),
CervicalMucusRecord::class to
READ_CERVICAL_MUCUS.substringAfter(READ_PERMISSION_PREFIX),
CyclingPedalingCadenceRecord::class to
READ_EXERCISE.substringAfter(READ_PERMISSION_PREFIX),
DistanceRecord::class to READ_DISTANCE.substringAfter(READ_PERMISSION_PREFIX),
ElevationGainedRecord::class to
READ_ELEVATION_GAINED.substringAfter(READ_PERMISSION_PREFIX),
ExerciseSessionRecord::class to
READ_EXERCISE.substringAfter(READ_PERMISSION_PREFIX),
FloorsClimbedRecord::class to
READ_FLOORS_CLIMBED.substringAfter(READ_PERMISSION_PREFIX),
HeartRateRecord::class to READ_HEART_RATE.substringAfter(READ_PERMISSION_PREFIX),
HeartRateVariabilityRmssdRecord::class to
READ_HEART_RATE_VARIABILITY.substringAfter(READ_PERMISSION_PREFIX),
HeightRecord::class to READ_HEIGHT.substringAfter(READ_PERMISSION_PREFIX),
HydrationRecord::class to READ_HYDRATION.substringAfter(READ_PERMISSION_PREFIX),
IntermenstrualBleedingRecord::class to
READ_INTERMENSTRUAL_BLEEDING.substringAfter(READ_PERMISSION_PREFIX),
LeanBodyMassRecord::class to
READ_LEAN_BODY_MASS.substringAfter(READ_PERMISSION_PREFIX),
MenstruationFlowRecord::class to
READ_MENSTRUATION.substringAfter(READ_PERMISSION_PREFIX),
MenstruationPeriodRecord::class to
READ_MENSTRUATION.substringAfter(READ_PERMISSION_PREFIX),
NutritionRecord::class to READ_NUTRITION.substringAfter(READ_PERMISSION_PREFIX),
OvulationTestRecord::class to
READ_OVULATION_TEST.substringAfter(READ_PERMISSION_PREFIX),
OxygenSaturationRecord::class to
READ_OXYGEN_SATURATION.substringAfter(READ_PERMISSION_PREFIX),
PowerRecord::class to READ_POWER.substringAfter(READ_PERMISSION_PREFIX),
RespiratoryRateRecord::class to
READ_RESPIRATORY_RATE.substringAfter(READ_PERMISSION_PREFIX),
RestingHeartRateRecord::class to
READ_RESTING_HEART_RATE.substringAfter(READ_PERMISSION_PREFIX),
SexualActivityRecord::class to
READ_SEXUAL_ACTIVITY.substringAfter(READ_PERMISSION_PREFIX),
SleepSessionRecord::class to READ_SLEEP.substringAfter(READ_PERMISSION_PREFIX),
SleepStageRecord::class to READ_SLEEP.substringAfter(READ_PERMISSION_PREFIX),
SpeedRecord::class to READ_SPEED.substringAfter(READ_PERMISSION_PREFIX),
StepsCadenceRecord::class to READ_STEPS.substringAfter(READ_PERMISSION_PREFIX),
StepsRecord::class to READ_STEPS.substringAfter(READ_PERMISSION_PREFIX),
TotalCaloriesBurnedRecord::class to
READ_TOTAL_CALORIES_BURNED.substringAfter(READ_PERMISSION_PREFIX),
Vo2MaxRecord::class to READ_VO2_MAX.substringAfter(READ_PERMISSION_PREFIX),
WeightRecord::class to READ_WEIGHT.substringAfter(READ_PERMISSION_PREFIX),
WheelchairPushesRecord::class to
READ_WHEELCHAIR_PUSHES.substringAfter(READ_PERMISSION_PREFIX),
)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is HealthPermission) return false
if (recordType != other.recordType) return false
if (accessType != other.accessType) return false
return true
}
override fun hashCode(): Int {
var result = recordType.hashCode()
result = 31 * result + accessType
return result
}
}