Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7728a006 authored by Hao Dong's avatar Hao Dong
Browse files

Use user id from PromptInfo instead of context for logo badge

Bug: 369219504
Test: manual test on work profile with testdpc
Test: atest PromptViewModelTest
Flag: EXEMPT bugfix

Change-Id: I2439e1ad3eeda0657a1babe3843bec4eb64a081f
parent dd3c9155
Loading
Loading
Loading
Loading
+109 −96
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ import android.hardware.biometrics.PromptVerticalListContentView
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.UserHandle
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.EnableFlags
import android.view.HapticFeedbackConstants
import android.view.HapticFeedbackConstants
@@ -97,13 +98,14 @@ import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
import platform.test.runner.parameterized.Parameters


private const val USER_ID = 4
private const val USER_ID = 4
private const val WORK_USER_ID = 100
private const val REQUEST_ID = 4L
private const val REQUEST_ID = 4L
private const val CHALLENGE = 2L
private const val CHALLENGE = 2L
private const val DELAY = 1000L
private const val DELAY = 1000L
private const val OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO = "should.use.activiy.logo"
private const val OP_PACKAGE_NAME_WITH_APP_LOGO = "biometric.testapp"
private const val OP_PACKAGE_NAME_WITH_APP_LOGO = "biometric.testapp"
private const val OP_PACKAGE_NAME_NO_ICON = "biometric.testapp.noicon"
private const val OP_PACKAGE_NAME_NO_LOGO_INFO = "biometric.testapp.nologoinfo"
private const val OP_PACKAGE_NAME_CAN_NOT_BE_FOUND = "can.not.be.found"
private const val OP_PACKAGE_NAME_CAN_NOT_BE_FOUND = "can.not.be.found"
private const val OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO = "should.use.activiy.logo"


@OptIn(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@SmallTest
@@ -120,13 +122,15 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa


    private val defaultLogoIconFromAppInfo = context.getDrawable(R.drawable.ic_android)
    private val defaultLogoIconFromAppInfo = context.getDrawable(R.drawable.ic_android)
    private val defaultLogoIconFromActivityInfo = context.getDrawable(R.drawable.ic_add)
    private val defaultLogoIconFromActivityInfo = context.getDrawable(R.drawable.ic_add)
    private val defaultLogoIconWithBadge = context.getDrawable(R.drawable.ic_alarm)
    private val logoResFromApp = R.drawable.ic_cake
    private val logoResFromApp = R.drawable.ic_cake
    private val logoDrawableFromAppRes = context.getDrawable(logoResFromApp)
    private val logoDrawableFromAppRes = context.getDrawable(logoResFromApp)
    private val logoBitmapFromApp = Bitmap.createBitmap(400, 400, Bitmap.Config.RGB_565)
    private val logoBitmapFromApp = Bitmap.createBitmap(400, 400, Bitmap.Config.RGB_565)
    private val defaultLogoDescriptionFromAppInfo = "Test Android App"
    private val defaultLogoDescriptionFromAppInfo = "Test Android App"
    private val defaultLogoDescriptionFromActivityInfo = "Test Coke App"
    private val defaultLogoDescriptionFromActivityInfo = "Test Coke App"
    private val defaultLogoDescriptionWithBadge = "Work app"
    private val logoDescriptionFromApp = "Test Cake App"
    private val logoDescriptionFromApp = "Test Cake App"
    private val packageNameForLogoWithOverrides = "should.use.overridden.logo"

    private val authInteractionProperties = AuthInteractionProperties()
    private val authInteractionProperties = AuthInteractionProperties()


    /** Prompt panel size padding */
    /** Prompt panel size padding */
@@ -173,55 +177,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa


    @Before
    @Before
    fun setup() {
    fun setup() {
        // Set up default logo info and app customized info
        setupLogo()
        whenever(kosmos.packageManager.getApplicationInfo(eq(OP_PACKAGE_NAME_NO_ICON), anyInt()))
            .thenReturn(applicationInfoNoIconOrDescription)
        whenever(
                kosmos.packageManager.getApplicationInfo(
                    eq(OP_PACKAGE_NAME_WITH_APP_LOGO),
                    anyInt(),
                )
            )
            .thenReturn(applicationInfoWithIconAndDescription)
        whenever(
                kosmos.packageManager.getApplicationInfo(
                    eq(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO),
                    anyInt(),
                )
            )
            .thenReturn(applicationInfoWithIconAndDescription)
        whenever(
                kosmos.packageManager.getApplicationInfo(
                    eq(OP_PACKAGE_NAME_CAN_NOT_BE_FOUND),
                    anyInt(),
                )
            )
            .thenThrow(NameNotFoundException())

        whenever(kosmos.packageManager.getActivityInfo(any(), anyInt())).thenReturn(activityInfo)
        whenever(kosmos.iconProvider.getIcon(activityInfo))
            .thenReturn(defaultLogoIconFromActivityInfo)
        whenever(activityInfo.loadLabel(kosmos.packageManager))
            .thenReturn(defaultLogoDescriptionFromActivityInfo)

        whenever(kosmos.packageManager.getApplicationIcon(applicationInfoWithIconAndDescription))
            .thenReturn(defaultLogoIconFromAppInfo)
        whenever(kosmos.packageManager.getApplicationLabel(applicationInfoWithIconAndDescription))
            .thenReturn(defaultLogoDescriptionFromAppInfo)
        whenever(kosmos.packageManager.getApplicationIcon(applicationInfoNoIconOrDescription))
            .thenReturn(null)
        whenever(kosmos.packageManager.getApplicationLabel(applicationInfoNoIconOrDescription))
            .thenReturn("")
        whenever(kosmos.packageManager.getUserBadgedIcon(any(), any())).then { it.getArgument(0) }
        whenever(kosmos.packageManager.getUserBadgedLabel(any(), any())).then { it.getArgument(0) }

        context.setMockPackageManager(kosmos.packageManager)
        overrideResource(logoResFromApp, logoDrawableFromAppRes)
        overrideResource(
            R.array.config_useActivityLogoForBiometricPrompt,
            arrayOf(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO),
        )

        overrideResource(R.dimen.biometric_dialog_fingerprint_icon_width, mockFingerprintIconWidth)
        overrideResource(R.dimen.biometric_dialog_fingerprint_icon_width, mockFingerprintIconWidth)
        overrideResource(
        overrideResource(
            R.dimen.biometric_dialog_fingerprint_icon_height,
            R.dimen.biometric_dialog_fingerprint_icon_height,
@@ -264,6 +220,74 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
                .build()
                .build()
    }
    }


    private fun setupLogo() {
        // Set up app customized logo
        overrideResource(logoResFromApp, logoDrawableFromAppRes)

        // Set up when activity info should be used
        overrideResource(
            R.array.config_useActivityLogoForBiometricPrompt,
            arrayOf(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO),
        )
        whenever(kosmos.packageManager.getActivityInfo(any(), anyInt())).thenReturn(activityInfo)
        whenever(kosmos.iconProvider.getIcon(activityInfo))
            .thenReturn(defaultLogoIconFromActivityInfo)
        whenever(activityInfo.loadLabel(kosmos.packageManager))
            .thenReturn(defaultLogoDescriptionFromActivityInfo)

        // Set up when application info should be used for default logo
        whenever(
                kosmos.packageManager.getApplicationInfo(
                    eq(OP_PACKAGE_NAME_WITH_APP_LOGO),
                    anyInt(),
                )
            )
            .thenReturn(applicationInfoWithIconAndDescription)
        whenever(
                kosmos.packageManager.getApplicationInfo(
                    eq(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO),
                    anyInt(),
                )
            )
            .thenReturn(applicationInfoWithIconAndDescription)
        whenever(kosmos.packageManager.getApplicationIcon(applicationInfoWithIconAndDescription))
            .thenReturn(defaultLogoIconFromAppInfo)
        whenever(kosmos.packageManager.getApplicationLabel(applicationInfoWithIconAndDescription))
            .thenReturn(defaultLogoDescriptionFromAppInfo)

        // Set up when package name cannot but found
        whenever(
                kosmos.packageManager.getApplicationInfo(
                    eq(OP_PACKAGE_NAME_CAN_NOT_BE_FOUND),
                    anyInt(),
                )
            )
            .thenThrow(NameNotFoundException())

        // Set up when no default logo from application info
        whenever(
                kosmos.packageManager.getApplicationInfo(eq(OP_PACKAGE_NAME_NO_LOGO_INFO), anyInt())
            )
            .thenReturn(applicationInfoNoIconOrDescription)
        whenever(kosmos.packageManager.getApplicationIcon(applicationInfoNoIconOrDescription))
            .thenReturn(null)
        whenever(kosmos.packageManager.getApplicationLabel(applicationInfoNoIconOrDescription))
            .thenReturn("")

        // Set up work badge
        whenever(kosmos.packageManager.getUserBadgedIcon(any(), eq(UserHandle.of(USER_ID)))).then {
            it.getArgument(0)
        }
        whenever(kosmos.packageManager.getUserBadgedLabel(any(), eq(UserHandle.of(USER_ID)))).then {
            it.getArgument(0)
        }
        whenever(kosmos.packageManager.getUserBadgedIcon(any(), eq(UserHandle.of(WORK_USER_ID))))
            .then { defaultLogoIconWithBadge }
        whenever(kosmos.packageManager.getUserBadgedLabel(any(), eq(UserHandle.of(WORK_USER_ID))))
            .then { defaultLogoDescriptionWithBadge }
        context.setMockPackageManager(kosmos.packageManager)
    }

    @Test
    @Test
    fun start_idle_and_show_authenticating() =
    fun start_idle_and_show_authenticating() =
        runGenericTest(doNotStart = true) {
        runGenericTest(doNotStart = true) {
@@ -1520,6 +1544,16 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            assertThat(logoInfo).isNotNull()
            assertThat(logoInfo).isNotNull()
            assertThat(logoInfo!!.first).isNull()
            assertThat(logoInfo!!.first).isNull()
            assertThat(logoInfo!!.second).isEqualTo("")
        }

    @Test
    fun logo_defaultIsNull() =
        runGenericTest(packageName = OP_PACKAGE_NAME_NO_LOGO_INFO) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            assertThat(logoInfo).isNotNull()
            assertThat(logoInfo!!.first).isNull()
            assertThat(logoInfo!!.second).isEqualTo("")
        }
        }


    @Test
    @Test
@@ -1527,32 +1561,39 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
        runGenericTest(packageName = OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) {
        runGenericTest(packageName = OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)


            assertThat(logoInfo).isNotNull()
            // 1. PM.getApplicationInfo(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) is set to return
            // 1. PM.getApplicationInfo(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) is set to return
            // applicationInfoWithIconAndDescription with "defaultLogoIconFromAppInfo",
            // applicationInfoWithIconAndDescription with "defaultLogoIconFromAppInfo",
            // 2. iconProvider.getIcon(activityInfo) is set to return
            // 2. iconProvider.getIcon(activityInfo) is set to return
            // "defaultLogoIconFromActivityInfo"
            // "defaultLogoIconFromActivityInfo"
            // For the apps with OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO, 2 should be called instead of 1
            // For the apps with OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO, 2 should be called instead of 1
            assertThat(logoInfo).isNotNull()
            assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconFromActivityInfo)
            assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconFromActivityInfo)
            // 1. PM.getApplicationInfo(OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) is set to return
            // applicationInfoWithIconAndDescription with "defaultLogoDescriptionFromAppInfo",
            // 2. activityInfo.loadLabel() is set to return defaultLogoDescriptionFromActivityInfo
            // For the apps with OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO, 2 should be called instead of 1
            assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionFromActivityInfo)
        }
        }


    @Test
    @Test
    fun logo_defaultIsNull() =
    fun logo_defaultFromApplicationInfo() = runGenericTest {
        runGenericTest(packageName = OP_PACKAGE_NAME_NO_ICON) {
        val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
        val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
        assertThat(logoInfo).isNotNull()
        assertThat(logoInfo).isNotNull()
            assertThat(logoInfo!!.first).isNull()
        assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconFromAppInfo)
        assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionFromAppInfo)
    }
    }


    @Test
    @Test
    fun logo_default() = runGenericTest {
    fun logo_defaultWithWorkBadge() =
        runGenericTest(userId = WORK_USER_ID) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            assertThat(logoInfo).isNotNull()
            assertThat(logoInfo).isNotNull()
        assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconFromAppInfo)
            assertThat(logoInfo!!.first).isEqualTo(defaultLogoIconWithBadge)
            assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionWithBadge)
        }
        }


    @Test
    @Test
    fun logo_resSetByApp() =
    fun logoRes_setByApp() =
        runGenericTest(logoRes = logoResFromApp) {
        runGenericTest(logoRes = logoResFromApp) {
            val expectedBitmap = context.getDrawable(logoResFromApp).toBitmap()
            val expectedBitmap = context.getDrawable(logoResFromApp).toBitmap()
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
@@ -1561,43 +1602,12 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
        }
        }


    @Test
    @Test
    fun logo_bitmapSetByApp() =
    fun logoBitmap_setByApp() =
        runGenericTest(logoBitmap = logoBitmapFromApp) {
        runGenericTest(logoBitmap = logoBitmapFromApp) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            assertThat((logoInfo!!.first as BitmapDrawable).bitmap).isEqualTo(logoBitmapFromApp)
            assertThat((logoInfo!!.first as BitmapDrawable).bitmap).isEqualTo(logoBitmapFromApp)
        }
        }


    @Test
    fun logoDescription_emptyIfPkgNameNotFound() =
        runGenericTest(packageName = OP_PACKAGE_NAME_CAN_NOT_BE_FOUND) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            assertThat(logoInfo!!.second).isEqualTo("")
        }

    @Test
    fun logoDescription_defaultFromActivityInfo() =
        runGenericTest(packageName = OP_PACKAGE_NAME_WITH_ACTIVITY_LOGO) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            // 1. PM.getApplicationInfo(packageNameForLogoWithOverrides) is set to return
            // applicationInfoWithIconAndDescription with defaultLogoDescription,
            // 2. activityInfo.loadLabel() is set to return defaultLogoDescriptionWithOverrides
            // For the apps with packageNameForLogoWithOverrides, 2 should be called instead of 1
            assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionFromActivityInfo)
        }

    @Test
    fun logoDescription_defaultIsEmpty() =
        runGenericTest(packageName = OP_PACKAGE_NAME_NO_ICON) {
            val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
            assertThat(logoInfo!!.second).isEqualTo("")
        }

    @Test
    fun logoDescription_default() = runGenericTest {
        val logoInfo by collectLastValue(kosmos.promptViewModel.logoInfo)
        assertThat(logoInfo!!.second).isEqualTo(defaultLogoDescriptionFromAppInfo)
    }

    @Test
    @Test
    fun logoDescription_setByApp() =
    fun logoDescription_setByApp() =
        runGenericTest(logoDescription = logoDescriptionFromApp) {
        runGenericTest(logoDescription = logoDescriptionFromApp) {
@@ -1766,6 +1776,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
        logoBitmap: Bitmap? = null,
        logoBitmap: Bitmap? = null,
        logoDescription: String? = null,
        logoDescription: String? = null,
        packageName: String = OP_PACKAGE_NAME_WITH_APP_LOGO,
        packageName: String = OP_PACKAGE_NAME_WITH_APP_LOGO,
        userId: Int = USER_ID,
        block: suspend TestScope.() -> Unit,
        block: suspend TestScope.() -> Unit,
    ) {
    ) {
        val topActivity = ComponentName(packageName, "test app")
        val topActivity = ComponentName(packageName, "test app")
@@ -1785,6 +1796,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
            logoBitmapFromApp = if (logoRes != 0) logoDrawableFromAppRes.toBitmap() else logoBitmap,
            logoBitmapFromApp = if (logoRes != 0) logoDrawableFromAppRes.toBitmap() else logoBitmap,
            logoDescriptionFromApp = logoDescription,
            logoDescriptionFromApp = logoDescription,
            packageName = packageName,
            packageName = packageName,
            userId = userId,
        )
        )


        kosmos.biometricStatusRepository.setFingerprintAcquiredStatus(
        kosmos.biometricStatusRepository.setFingerprintAcquiredStatus(
@@ -2010,6 +2022,7 @@ private fun PromptSelectorInteractor.initializePrompt(
    logoBitmapFromApp: Bitmap? = null,
    logoBitmapFromApp: Bitmap? = null,
    logoDescriptionFromApp: String? = null,
    logoDescriptionFromApp: String? = null,
    packageName: String = OP_PACKAGE_NAME_WITH_APP_LOGO,
    packageName: String = OP_PACKAGE_NAME_WITH_APP_LOGO,
    userId: Int = USER_ID,
) {
) {
    val info =
    val info =
        PromptInfo().apply {
        PromptInfo().apply {
@@ -2028,7 +2041,7 @@ private fun PromptSelectorInteractor.initializePrompt(


    setPrompt(
    setPrompt(
        info,
        info,
        USER_ID,
        userId,
        REQUEST_ID,
        REQUEST_ID,
        BiometricModalities(fingerprintProperties = fingerprint, faceProperties = face),
        BiometricModalities(fingerprintProperties = fingerprint, faceProperties = face),
        CHALLENGE,
        CHALLENGE,
+20 −27
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import android.util.Log
import android.util.RotationUtils
import android.util.RotationUtils
import android.view.HapticFeedbackConstants
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import android.view.MotionEvent
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.keyguard.AuthInteractionProperties
import com.android.keyguard.AuthInteractionProperties
import com.android.launcher3.icons.IconProvider
import com.android.launcher3.icons.IconProvider
import com.android.systemui.Flags.msdlFeedback
import com.android.systemui.Flags.msdlFeedback
@@ -71,7 +72,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.flow.update
import com.android.app.tracing.coroutines.launchTraced as launch


/** ViewModel for BiometricPrompt. */
/** ViewModel for BiometricPrompt. */
class PromptViewModel
class PromptViewModel
@@ -973,7 +973,7 @@ constructor(
/**
/**
 * The order of getting logo icon/description is:
 * The order of getting logo icon/description is:
 * 1. If the app sets customized icon/description, use the passed-in value
 * 1. If the app sets customized icon/description, use the passed-in value
 * 2. If shouldShowLogoWithOverrides(), use activityInfo to get icon/description
 * 2. If shouldUseActivityLogo(), use activityInfo to get icon/description
 * 3. Otherwise, use applicationInfo to get icon/description
 * 3. Otherwise, use applicationInfo to get icon/description
 */
 */
private fun Context.getUserBadgedLogoInfo(
private fun Context.getUserBadgedLogoInfo(
@@ -981,6 +981,7 @@ private fun Context.getUserBadgedLogoInfo(
    iconProvider: IconProvider,
    iconProvider: IconProvider,
    activityTaskManager: ActivityTaskManager,
    activityTaskManager: ActivityTaskManager,
): Pair<Drawable?, String> {
): Pair<Drawable?, String> {
    // If the app sets customized icon/description, use the passed-in value directly
    var icon: Drawable? =
    var icon: Drawable? =
        if (prompt.logoBitmap != null) BitmapDrawable(resources, prompt.logoBitmap) else null
        if (prompt.logoBitmap != null) BitmapDrawable(resources, prompt.logoBitmap) else null
    var label = prompt.logoDescription ?: ""
    var label = prompt.logoDescription ?: ""
@@ -993,36 +994,28 @@ private fun Context.getUserBadgedLogoInfo(
    if (componentName != null && shouldUseActivityLogo(componentName)) {
    if (componentName != null && shouldUseActivityLogo(componentName)) {
        val activityInfo = getActivityInfo(componentName)
        val activityInfo = getActivityInfo(componentName)
        if (activityInfo != null) {
        if (activityInfo != null) {
            if (icon == null) {
            icon = icon ?: iconProvider.getIcon(activityInfo)
                icon = iconProvider.getIcon(activityInfo)
            label = label.ifEmpty { activityInfo.loadLabel(packageManager).toString() }
            }
            if (label.isEmpty()) {
                label = activityInfo.loadLabel(packageManager).toString()
            }
        }
        }
    }
    }
    if (icon != null && label.isNotEmpty()) {
        return Pair(icon, label)
    }

    // Use applicationInfo for other cases
    // Use applicationInfo for other cases
    if (icon == null || label.isEmpty()) {
        val appInfo = prompt.getApplicationInfo(this, componentName)
        val appInfo = prompt.getApplicationInfo(this, componentName)
    if (appInfo == null) {
        if (appInfo != null) {
        Log.w(PromptViewModel.TAG, "Cannot find app logo for package $opPackageName")
            icon = icon ?: packageManager.getApplicationIcon(appInfo)
            label = label.ifEmpty { packageManager.getApplicationLabel(appInfo).toString() }
        } else {
        } else {
        if (icon == null) {
            Log.w(PromptViewModel.TAG, "Cannot find app logo for package $opPackageName")
            icon = packageManager.getApplicationIcon(appInfo)
        }
        if (label.isEmpty()) {
            label =
                packageManager
                    .getUserBadgedLabel(
                        packageManager.getApplicationLabel(appInfo),
                        UserHandle.of(userId),
                    )
                    .toString()
        }
        }
    }
    }

    // Add user badge
    val userHandle = UserHandle.of(prompt.userInfo.userId)
    if (label.isNotEmpty()) {
        label = packageManager.getUserBadgedLabel(label, userHandle).toString()
    }
    icon = icon?.let { packageManager.getUserBadgedIcon(it, userHandle) }

    return Pair(icon, label)
    return Pair(icon, label)
}
}