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

Commit 2a71b780 authored by Yuichiro Hanada's avatar Yuichiro Hanada
Browse files

Do not crash when a package is not found

It's possible that an app is uninstalled before creating an app header.
WMShell should not crash even in that case.

Bug: 404119367
Test: WMShellUnitTests
Flag: EXEMPT crash fix
Change-Id: Ib8248eac7136bcbad74cf2317c0dd9c1dac71cce
parent 8fbbf6f9
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@ import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.graphics.Bitmap
import android.os.LocaleList
import android.os.UserHandle
import android.util.Slog
import androidx.tracing.Trace
import com.android.internal.annotations.VisibleForTesting
import com.android.launcher3.icons.BaseIconFactory
@@ -113,7 +115,6 @@ class WindowDecorTaskResourceLoader(
            return cachedResources.appName
        }
        val resources = loadAppResources(taskInfo)
        taskToResourceCache[taskInfo.taskId] = resources
        localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales()
        return resources.appName
    }
@@ -127,7 +128,6 @@ class WindowDecorTaskResourceLoader(
            return cachedResources.appIcon
        }
        val resources = loadAppResources(taskInfo)
        taskToResourceCache[taskInfo.taskId] = resources
        localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales()
        return resources.appIcon
    }
@@ -141,7 +141,6 @@ class WindowDecorTaskResourceLoader(
            return cachedResources.veilIcon
        }
        val resources = loadAppResources(taskInfo)
        taskToResourceCache[taskInfo.taskId] = resources
        localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales()
        return resources.veilIcon
    }
@@ -178,7 +177,21 @@ class WindowDecorTaskResourceLoader(
            val badgedAppIconDrawable = pm.getUserBadgedIcon(appIconDrawable, taskInfo.userHandle())
            val appIcon = headerIconFactory.createIconBitmap(badgedAppIconDrawable, /* scale= */ 1f)
            val veilIcon = veilIconFactory.createScaledBitmap(appIconDrawable, MODE_DEFAULT)
            return AppResources(appName = appName, appIcon = appIcon, veilIcon = veilIcon)
            val appResources =
                AppResources(appName = appName, appIcon = appIcon, veilIcon = veilIcon)
            taskToResourceCache[taskInfo.taskId] = appResources
            return appResources
        } catch (e: NameNotFoundException) {
            Slog.e(TAG, "Failed to get app resources")
            val pm =
                userProfilesContexts
                .getOrCreate(taskInfo.userId)
                .packageManager
            val defaultIconDrawable = pm.getDefaultActivityIcon()
            val appIcon = headerIconFactory.createIconBitmap(defaultIconDrawable, /* scale= */ 1f)
            val veilIcon = veilIconFactory.createScaledBitmap(defaultIconDrawable, MODE_DEFAULT)
            // Do not cache the result when loading failed.
            return AppResources(appName = "", appIcon = appIcon, veilIcon = veilIcon)
        } finally {
            Trace.endSection()
        }
+24 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.graphics.drawable.Drawable
import android.os.LocaleList
import android.os.UserHandle
@@ -50,6 +51,7 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
@@ -211,6 +213,28 @@ class WindowDecorTaskResourceLoaderTest : ShellTestCase() {
        assertThrows(Exception::class.java) { loader.getName(task) }
    }

    @Test
    fun testGet_nonexistentPackage_returnsDefaultAndDontCache() {
        val componentName = ComponentName("com.foo", "BarActivity")
        val appIconDrawable = mock<Drawable>()
        val task = TestRunningTaskInfoBuilder()
            .setUserId(context.userId)
            .setBaseIntent(Intent().apply { component = componentName })
            .build()
        loader.onWindowDecorCreated(task)
        doReturn(appIconDrawable).whenever(mockPackageManager).getDefaultActivityIcon()
        whenever(mockHeaderIconFactory.createIconBitmap(appIconDrawable, 1f))
            .thenReturn(mock())
        whenever(mockVeilIconFactory.createScaledBitmap(appIconDrawable, MODE_DEFAULT))
            .thenReturn(mock())
        doThrow(NameNotFoundException()).whenever(mockPackageManager).getActivityInfo(eq(componentName), anyInt())

        loader.getVeilIcon(task)

        verify(mockVeilIconFactory).createScaledBitmap(appIconDrawable, MODE_DEFAULT)
        assertThat(loader.taskToResourceCache[task.taskId]).isNull()
    }

    private fun createTaskInfo(userId: Int): ActivityManager.RunningTaskInfo {
        val appIconDrawable = mock<Drawable>()
        val badgedAppIconDrawable = mock<Drawable>()