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 19 /** 20 * Copyright (C) 2022 The Android Open Source Project 21 * 22 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 23 * in compliance with the License. You may obtain a copy of the License at 24 * 25 * ``` 26 * http://www.apache.org/licenses/LICENSE-2.0 27 * ``` 28 * 29 * Unless required by applicable law or agreed to in writing, software distributed under the License 30 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 31 * or implied. See the License for the specific language governing permissions and limitations under 32 * the License. 33 */ 34 package com.android.healthconnect.controller.shared.app 35 36 import android.content.Context 37 import android.graphics.Bitmap 38 import android.graphics.drawable.BitmapDrawable 39 import android.graphics.drawable.Drawable 40 import android.health.connect.ApplicationInfoResponse 41 import android.health.connect.HealthConnectManager 42 import android.health.connect.datatypes.AppInfo 43 import android.util.Log 44 import androidx.core.os.asOutcomeReceiver 45 import com.android.healthconnect.controller.service.IoDispatcher 46 import dagger.hilt.android.qualifiers.ApplicationContext 47 import javax.inject.Inject 48 import javax.inject.Singleton 49 import kotlinx.coroutines.CoroutineDispatcher 50 import kotlinx.coroutines.suspendCancellableCoroutine 51 import kotlinx.coroutines.withContext 52 53 @Singleton 54 class GetContributorAppInfoUseCase 55 @Inject 56 constructor( 57 private val healthConnectManager: HealthConnectManager, 58 @ApplicationContext private val context: Context, 59 @IoDispatcher private val dispatcher: CoroutineDispatcher 60 ) : IGetContributorAppInfoUseCase { 61 companion object { 62 private const val TAG = "GetContributorAppInfo" 63 } 64 65 override suspend fun invoke(): Map<String, AppMetadata> = 66 withContext(dispatcher) { 67 try { 68 val appInfoList = 69 suspendCancellableCoroutine<ApplicationInfoResponse> { continuation -> 70 healthConnectManager.getContributorApplicationsInfo( 71 Runnable::run, continuation.asOutcomeReceiver()) 72 } 73 .applicationInfoList 74 appInfoList.associate { it.packageName to toAppMetadata(it) } 75 } catch (e: Exception) { 76 Log.e(TAG, "GetContributorApplicationsInfoUseCase", e) 77 emptyMap() 78 } 79 } 80 81 private fun toAppMetadata(appInfo: AppInfo): AppMetadata { 82 return AppMetadata( 83 packageName = appInfo.packageName, 84 appName = 85 appInfo.name 86 ?: appInfo.packageName, // default to package name if appInfo name is null 87 icon = getIcon(appInfo.icon)) 88 } 89 90 private fun getIcon(bitmap: Bitmap?): Drawable? { 91 return bitmap?.let { BitmapDrawable(context.resources, it) } 92 } 93 } 94 95 interface IGetContributorAppInfoUseCase { invokenull96 suspend operator fun invoke(): Map<String, AppMetadata> 97 } 98