Merge "Fix crash of PictureInPicture" into udc-dev am: 5b042e2feb
am: a9a229665b
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/23408018 Change-Id: Ic4f862141920da6b3d392c48158fd94eadf1758e Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import android.content.pm.ApplicationInfo
|
|||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager.GET_ACTIVITIES
|
import android.content.pm.PackageManager.GET_ACTIVITIES
|
||||||
import android.content.pm.PackageManager.PackageInfoFlags
|
import android.content.pm.PackageManager.PackageInfoFlags
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
@@ -56,9 +57,8 @@ class PictureInPictureListModel(private val context: Context) :
|
|||||||
private val packageManager = context.packageManager
|
private val packageManager = context.packageManager
|
||||||
|
|
||||||
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
|
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
|
||||||
userIdFlow.map(::getPictureInPicturePackages).combine(appListFlow) {
|
userIdFlow.map(::getPictureInPicturePackages)
|
||||||
pictureInPicturePackages,
|
.combine(appListFlow) { pictureInPicturePackages, appList ->
|
||||||
appList ->
|
|
||||||
appList.map { app ->
|
appList.map { app ->
|
||||||
createPictureInPictureRecord(
|
createPictureInPictureRecord(
|
||||||
app = app,
|
app = app,
|
||||||
@@ -67,15 +67,11 @@ class PictureInPictureListModel(private val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformItem(app: ApplicationInfo): PictureInPictureRecord {
|
override fun transformItem(app: ApplicationInfo) = createPictureInPictureRecord(
|
||||||
return createPictureInPictureRecord(
|
|
||||||
app = app,
|
app = app,
|
||||||
isSupport = app.installed &&
|
isSupport = app.installed &&
|
||||||
packageManager
|
getPackageAndActivityInfo(app)?.supportsPictureInPicture() == true,
|
||||||
.getPackageInfoAsUser(app.packageName, GET_ACTIVITIES_FLAGS, app.userId)
|
|
||||||
.supportsPictureInPicture(),
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
private fun createPictureInPictureRecord(app: ApplicationInfo, isSupport: Boolean) =
|
private fun createPictureInPictureRecord(app: ApplicationInfo, isSupport: Boolean) =
|
||||||
PictureInPictureRecord(
|
PictureInPictureRecord(
|
||||||
@@ -103,13 +99,36 @@ class PictureInPictureListModel(private val context: Context) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPictureInPicturePackages(userId: Int): Set<String> =
|
private fun getPictureInPicturePackages(userId: Int): Set<String> =
|
||||||
packageManager
|
getPackageAndActivityInfoList(userId)
|
||||||
.getInstalledPackagesAsUser(GET_ACTIVITIES_FLAGS, userId)
|
|
||||||
.filter { it.supportsPictureInPicture() }
|
.filter { it.supportsPictureInPicture() }
|
||||||
.map { it.packageName }
|
.map { it.packageName }
|
||||||
.toSet()
|
.toSet()
|
||||||
|
|
||||||
|
private fun getPackageAndActivityInfo(app: ApplicationInfo): PackageInfo? = try {
|
||||||
|
packageManager.getPackageInfoAsUser(app.packageName, GET_ACTIVITIES_FLAGS, app.userId)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Query PackageManager.getPackageInfoAsUser() with GET_ACTIVITIES_FLAGS could cause
|
||||||
|
// exception sometimes. Since we reply on this flag to retrieve the Picture In Picture
|
||||||
|
// packages, we need to catch the exception to alleviate the impact before PackageManager
|
||||||
|
// fixing this issue or provide a better api.
|
||||||
|
Log.e(TAG, "Exception while getPackageInfoAsUser", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPackageAndActivityInfoList(userId: Int): List<PackageInfo> = try {
|
||||||
|
packageManager.getInstalledPackagesAsUser(GET_ACTIVITIES_FLAGS, userId)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Query PackageManager.getPackageInfoAsUser() with GET_ACTIVITIES_FLAGS could cause
|
||||||
|
// exception sometimes. Since we reply on this flag to retrieve the Picture In Picture
|
||||||
|
// packages, we need to catch the exception to alleviate the impact before PackageManager
|
||||||
|
// fixing this issue or provide a better api.
|
||||||
|
Log.e(TAG, "Exception while getInstalledPackagesAsUser", e)
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val TAG = "PictureInPictureListModel"
|
||||||
|
|
||||||
private fun PackageInfo.supportsPictureInPicture() =
|
private fun PackageInfo.supportsPictureInPicture() =
|
||||||
activities?.any(ActivityInfo::supportsPictureInPicture) ?: false
|
activities?.any(ActivityInfo::supportsPictureInPicture) ?: false
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ import android.content.pm.ApplicationInfo
|
|||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.PackageManager.PackageInfoFlags
|
import android.content.pm.PackageManager.PackageInfoFlags
|
||||||
|
import android.os.DeadSystemRuntimeException
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
@@ -100,6 +101,23 @@ class PictureInPictureTest {
|
|||||||
assertThat(record.isSupport).isTrue()
|
assertThat(record.isSupport).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun transform_getInstalledPackagesAsUserThrowsException_treatAsNotSupported() = runTest {
|
||||||
|
whenever(packageManager.getInstalledPackagesAsUser(any<PackageInfoFlags>(), anyInt()))
|
||||||
|
.thenThrow(DeadSystemRuntimeException())
|
||||||
|
|
||||||
|
val recordListFlow = listModel.transform(
|
||||||
|
userIdFlow = flowOf(USER_ID),
|
||||||
|
appListFlow = flowOf(listOf(PICTURE_IN_PICTURE_APP)),
|
||||||
|
)
|
||||||
|
|
||||||
|
val recordList = recordListFlow.first()
|
||||||
|
assertThat(recordList).hasSize(1)
|
||||||
|
val record = recordList[0]
|
||||||
|
assertThat(record.app).isSameInstanceAs(PICTURE_IN_PICTURE_APP)
|
||||||
|
assertThat(record.isSupport).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transformItem() {
|
fun transformItem() {
|
||||||
whenever(
|
whenever(
|
||||||
@@ -114,6 +132,20 @@ class PictureInPictureTest {
|
|||||||
assertThat(record.isSupport).isTrue()
|
assertThat(record.isSupport).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun transformItem_getPackageInfoAsUserThrowsException_treatAsNotSupported() {
|
||||||
|
whenever(
|
||||||
|
packageManager.getPackageInfoAsUser(
|
||||||
|
eq(PICTURE_IN_PICTURE_PACKAGE_NAME), any<PackageInfoFlags>(), eq(USER_ID)
|
||||||
|
)
|
||||||
|
).thenThrow(DeadSystemRuntimeException())
|
||||||
|
|
||||||
|
val record = listModel.transformItem(PICTURE_IN_PICTURE_APP)
|
||||||
|
|
||||||
|
assertThat(record.app).isSameInstanceAs(PICTURE_IN_PICTURE_APP)
|
||||||
|
assertThat(record.isSupport).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun filter_isSupport() = runTest {
|
fun filter_isSupport() = runTest {
|
||||||
val record = createRecord(isSupport = true)
|
val record = createRecord(isSupport = true)
|
||||||
|
Reference in New Issue
Block a user