1 /* <lambda>null2 * Copyright (C) 2023 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 */ 18 package com.android.healthconnect.controller.shared.app 19 20 import android.content.Context 21 import android.graphics.Bitmap 22 import android.graphics.drawable.BitmapDrawable 23 import android.graphics.drawable.Drawable 24 import android.health.connect.ApplicationInfoResponse 25 import android.health.connect.HealthConnectManager 26 import android.health.connect.datatypes.AppInfo 27 import android.util.Log 28 import androidx.core.os.asOutcomeReceiver 29 import com.android.healthconnect.controller.service.IoDispatcher 30 import dagger.hilt.android.qualifiers.ApplicationContext 31 import javax.inject.Inject 32 import javax.inject.Singleton 33 import kotlinx.coroutines.CoroutineDispatcher 34 import kotlinx.coroutines.suspendCancellableCoroutine 35 import kotlinx.coroutines.withContext 36 37 @Singleton 38 class GetContributorAppInfoUseCase 39 @Inject 40 constructor( 41 private val healthConnectManager: HealthConnectManager, 42 @ApplicationContext private val context: Context, 43 @IoDispatcher private val dispatcher: CoroutineDispatcher, 44 ) : IGetContributorAppInfoUseCase { 45 companion object { 46 private const val TAG = "GetContributorAppInfo" 47 } 48 49 override suspend fun invoke(): Map<String, AppMetadata> = 50 withContext(dispatcher) { 51 try { 52 val appInfoList = 53 suspendCancellableCoroutine<ApplicationInfoResponse> { continuation -> 54 healthConnectManager.getContributorApplicationsInfo( 55 Runnable::run, 56 continuation.asOutcomeReceiver(), 57 ) 58 } 59 .applicationInfoList 60 appInfoList.associate { it.packageName to toAppMetadata(it) } 61 } catch (e: Exception) { 62 Log.e(TAG, "GetContributorApplicationsInfoUseCase", e) 63 emptyMap() 64 } 65 } 66 67 private fun toAppMetadata(appInfo: AppInfo): AppMetadata { 68 return AppMetadata( 69 packageName = appInfo.packageName, 70 appName = 71 appInfo.name 72 ?: appInfo.packageName, // default to package name if appInfo name is null 73 icon = getIcon(appInfo.icon), 74 ) 75 } 76 77 private fun getIcon(bitmap: Bitmap?): Drawable? { 78 return bitmap?.let { BitmapDrawable(context.resources, it) } 79 } 80 } 81 82 interface IGetContributorAppInfoUseCase { invokenull83 suspend operator fun invoke(): Map<String, AppMetadata> 84 } 85