blob: ea954f14100eaf3ea89be46603d42109276336da [file] [log] [blame]
/*
* 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 com.android.healthconnect.controller.dataaccess
import com.android.healthconnect.controller.LoadPermissionTypeContributorAppsUseCase
import com.android.healthconnect.controller.dataaccess.HealthDataAccessViewModel.DataAccessAppState
import com.android.healthconnect.controller.permissions.api.GetGrantedHealthPermissionsUseCase
import com.android.healthconnect.controller.permissions.data.HealthPermission
import com.android.healthconnect.controller.permissions.data.HealthPermissionType
import com.android.healthconnect.controller.permissions.data.PermissionsAccessType
import com.android.healthconnect.controller.service.IoDispatcher
import com.android.healthconnect.controller.shared.HealthPermissionReader
import com.android.healthconnect.controller.shared.app.AppInfoReader
import com.android.healthconnect.controller.shared.app.AppMetadata
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
@Singleton
class LoadDataAccessUseCase
@Inject
constructor(
private val loadPermissionTypeContributorAppsUseCase: LoadPermissionTypeContributorAppsUseCase,
private val loadGrantedHealthPermissionsUseCase: GetGrantedHealthPermissionsUseCase,
private val healthPermissionReader: HealthPermissionReader,
private val appInfoReader: AppInfoReader,
@IoDispatcher private val dispatcher: CoroutineDispatcher
) {
/** Returns a map of [DataAccessAppState] to apps. */
suspend operator fun invoke(
permissionType: HealthPermissionType
): Map<DataAccessAppState, List<AppMetadata>> =
withContext(dispatcher) {
val appsWithHealthPermissions: List<String> =
healthPermissionReader.getAppsWithHealthPermissions()
val contributingApps: List<AppMetadata> =
loadPermissionTypeContributorAppsUseCase.invoke(permissionType)
val readAppMetadataSet: MutableSet<AppMetadata> = mutableSetOf()
val writeAppMetadataSet: MutableSet<AppMetadata> = mutableSetOf()
val writeAppPackageNameSet: MutableSet<String> = mutableSetOf()
val inactiveAppMetadataSet: MutableSet<AppMetadata> = mutableSetOf()
appsWithHealthPermissions.forEach {
val permissionsPerPackage: List<String> = loadGrantedHealthPermissionsUseCase(it)
// Apps that can READ the given healthPermissionType.
if (permissionsPerPackage.contains(
HealthPermission(permissionType, PermissionsAccessType.READ).toString())) {
readAppMetadataSet.add(appInfoReader.getAppMetadata(it))
}
// Apps that can WRITE the given healthPermissionType.
if (permissionsPerPackage.contains(
HealthPermission(permissionType, PermissionsAccessType.WRITE).toString())) {
writeAppMetadataSet.add(appInfoReader.getAppMetadata(it))
writeAppPackageNameSet.add(it)
}
}
// Apps that are inactive: can no longer WRITE, but still have data in Health Connect.
contributingApps.forEach { app ->
if (!writeAppPackageNameSet.contains(app.packageName)) {
inactiveAppMetadataSet.add(app)
}
}
mapOf(
DataAccessAppState.Read to alphabeticallySortedMetadataList(readAppMetadataSet),
DataAccessAppState.Write to alphabeticallySortedMetadataList(writeAppMetadataSet),
DataAccessAppState.Inactive to
alphabeticallySortedMetadataList(inactiveAppMetadataSet))
}
private fun alphabeticallySortedMetadataList(
packageNames: Set<AppMetadata>
): List<AppMetadata> {
return packageNames
.stream()
.sorted(Comparator.comparing { appMetaData -> appMetaData.appName })
.toList()
}
}