Merge "[Partial screensharing] Fix crash when having a recents app available only in work profile" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
78826d1eb5
@@ -19,6 +19,7 @@ package com.android.systemui.mediaprojection.appselector
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.android.launcher3.icons.IconFactory
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.media.MediaProjectionAppSelectorActivity
|
import com.android.systemui.media.MediaProjectionAppSelectorActivity
|
||||||
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
|
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
|
||||||
@@ -91,6 +92,11 @@ interface MediaProjectionAppSelectorModule {
|
|||||||
activity: MediaProjectionAppSelectorActivity
|
activity: MediaProjectionAppSelectorActivity
|
||||||
): ConfigurationController = ConfigurationControllerImpl(activity)
|
): ConfigurationController = ConfigurationControllerImpl(activity)
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun bindIconFactory(
|
||||||
|
context: Context
|
||||||
|
): IconFactory = IconFactory.obtain(context)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@MediaProjectionAppSelector
|
@MediaProjectionAppSelector
|
||||||
@MediaProjectionAppSelectorScope
|
@MediaProjectionAppSelectorScope
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ package com.android.systemui.mediaprojection.appselector.data
|
|||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.PackageManager.ComponentInfoFlags
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import com.android.launcher3.icons.BaseIconFactory.IconOptions
|
import com.android.launcher3.icons.BaseIconFactory.IconOptions
|
||||||
import com.android.launcher3.icons.IconFactory
|
import com.android.launcher3.icons.IconFactory
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
|
import com.android.systemui.shared.system.PackageManagerWrapper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Provider
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@@ -38,14 +39,18 @@ class IconLoaderLibAppIconLoader
|
|||||||
constructor(
|
constructor(
|
||||||
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val packageManager: PackageManager
|
// Use wrapper to access hidden API that allows to get ActivityInfo for any user id
|
||||||
|
private val packageManagerWrapper: PackageManagerWrapper,
|
||||||
|
private val packageManager: PackageManager,
|
||||||
|
private val iconFactoryProvider: Provider<IconFactory>
|
||||||
) : AppIconLoader {
|
) : AppIconLoader {
|
||||||
|
|
||||||
override suspend fun loadIcon(userId: Int, component: ComponentName): Drawable? =
|
override suspend fun loadIcon(userId: Int, component: ComponentName): Drawable? =
|
||||||
withContext(backgroundDispatcher) {
|
withContext(backgroundDispatcher) {
|
||||||
IconFactory.obtain(context).use<IconFactory, Drawable?> { iconFactory ->
|
iconFactoryProvider.get().use<IconFactory, Drawable?> { iconFactory ->
|
||||||
val activityInfo = packageManager
|
val activityInfo =
|
||||||
.getActivityInfo(component, ComponentInfoFlags.of(0))
|
packageManagerWrapper.getActivityInfo(component, userId)
|
||||||
|
?: return@withContext null
|
||||||
val icon = activityInfo.loadIcon(packageManager) ?: return@withContext null
|
val icon = activityInfo.loadIcon(packageManager) ?: return@withContext null
|
||||||
val userHandler = UserHandle.of(userId)
|
val userHandler = UserHandle.of(userId)
|
||||||
val options = IconOptions().apply { setUser(userHandler) }
|
val options = IconOptions().apply { setUser(userHandler) }
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.mediaprojection.appselector.data
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.launcher3.icons.BitmapInfo
|
||||||
|
import com.android.launcher3.icons.FastBitmapDrawable
|
||||||
|
import com.android.launcher3.icons.IconFactory
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.shared.system.PackageManagerWrapper
|
||||||
|
import com.android.systemui.util.mockito.any
|
||||||
|
import com.android.systemui.util.mockito.eq
|
||||||
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import com.android.systemui.util.mockito.whenever
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
class IconLoaderLibAppIconLoaderTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private val iconFactory: IconFactory = mock()
|
||||||
|
private val packageManagerWrapper: PackageManagerWrapper = mock()
|
||||||
|
private val packageManager: PackageManager = mock()
|
||||||
|
private val dispatcher = Dispatchers.Unconfined
|
||||||
|
|
||||||
|
private val appIconLoader =
|
||||||
|
IconLoaderLibAppIconLoader(
|
||||||
|
backgroundDispatcher = dispatcher,
|
||||||
|
context = context,
|
||||||
|
packageManagerWrapper = packageManagerWrapper,
|
||||||
|
packageManager = packageManager,
|
||||||
|
iconFactoryProvider = { iconFactory }
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loadIcon_loadsIconUsingTheSameUserId() {
|
||||||
|
val icon = createIcon()
|
||||||
|
val component = ComponentName("com.test", "TestApplication")
|
||||||
|
givenIcon(component, userId = 123, icon = icon)
|
||||||
|
|
||||||
|
val loadedIcon = runBlocking { appIconLoader.loadIcon(userId = 123, component = component) }
|
||||||
|
|
||||||
|
assertThat(loadedIcon).isEqualTo(icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenIcon(component: ComponentName, userId: Int, icon: FastBitmapDrawable) {
|
||||||
|
val activityInfo = mock<ActivityInfo>()
|
||||||
|
whenever(packageManagerWrapper.getActivityInfo(component, userId)).thenReturn(activityInfo)
|
||||||
|
val rawIcon = mock<Drawable>()
|
||||||
|
whenever(activityInfo.loadIcon(packageManager)).thenReturn(rawIcon)
|
||||||
|
|
||||||
|
val bitmapInfo = mock<BitmapInfo>()
|
||||||
|
whenever(iconFactory.createBadgedIconBitmap(eq(rawIcon), any())).thenReturn(bitmapInfo)
|
||||||
|
whenever(bitmapInfo.newIcon(context)).thenReturn(icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createIcon(): FastBitmapDrawable =
|
||||||
|
FastBitmapDrawable(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user