<lambda>null1package com.android.healthconnect.controller.permissiontypes.api 2 3 import android.health.connect.HealthConnectManager 4 import android.health.connect.HealthDataCategory 5 import android.health.connect.RecordTypeInfoResponse 6 import android.health.connect.datatypes.DataOrigin 7 import android.health.connect.datatypes.Record 8 import androidx.core.os.asOutcomeReceiver 9 import com.android.healthconnect.controller.service.IoDispatcher 10 import com.android.healthconnect.controller.shared.HealthDataCategoryInt 11 import com.android.healthconnect.controller.shared.app.AppInfoReader 12 import com.android.healthconnect.controller.shared.app.AppMetadata 13 import javax.inject.Inject 14 import javax.inject.Singleton 15 import kotlinx.coroutines.CoroutineDispatcher 16 import kotlinx.coroutines.suspendCancellableCoroutine 17 import kotlinx.coroutines.withContext 18 19 @Singleton 20 class LoadContributingAppsUseCase 21 @Inject 22 constructor( 23 private val appInfoReader: AppInfoReader, 24 private val healthConnectManager: HealthConnectManager, 25 @IoDispatcher private val dispatcher: CoroutineDispatcher 26 ) { 27 28 /** Returns list of contributing apps for selected [HealthDataCategory] */ 29 suspend operator fun invoke(category: @HealthDataCategoryInt Int): List<AppMetadata> = 30 withContext(dispatcher) { 31 val appsList: MutableSet<AppMetadata> = mutableSetOf() 32 val contributingAppsList = getListOfContributingApps(category) 33 contributingAppsList.forEach { contributingApp -> 34 if (appsList.none { it.packageName == contributingApp }) { 35 appsList.add(appInfoReader.getAppMetadata(contributingApp)) 36 } 37 } 38 alphabeticallySortedMetadataList(appsList) 39 } 40 41 /** Returns list of contributing apps for selected [HealthDataCategory] */ 42 private suspend fun getListOfContributingApps( 43 category: @HealthDataCategoryInt Int 44 ): List<String> = 45 withContext(dispatcher) { 46 try { 47 val recordTypeInfoMap: Map<Class<out Record>, RecordTypeInfoResponse> = 48 suspendCancellableCoroutine { continuation -> 49 healthConnectManager.queryAllRecordTypesInfo( 50 Runnable::run, continuation.asOutcomeReceiver()) 51 } 52 filterContributingApps(category, recordTypeInfoMap).map { it.packageName } 53 } catch (e: Exception) { 54 emptyList() 55 } 56 } 57 58 /** 59 * Filters list of contributing apps for selected [HealthDataCategory] from all record type 60 * information 61 */ 62 private fun filterContributingApps( 63 category: @HealthDataCategoryInt Int, 64 recordTypeInfoMap: Map<Class<out Record>, RecordTypeInfoResponse> 65 ): List<DataOrigin> = 66 recordTypeInfoMap.values 67 .filter { it.dataCategory == category && it.contributingPackages.isNotEmpty() } 68 .map { it.contributingPackages } 69 .flatten() 70 71 /** Sorts list of App Metadata alphabetically */ 72 private fun alphabeticallySortedMetadataList( 73 packageNames: Set<AppMetadata> 74 ): List<AppMetadata> { 75 return packageNames 76 .stream() 77 .sorted(Comparator.comparing { appMetaData -> appMetaData.appName }) 78 .toList() 79 } 80 } 81