Merge "Fix flicker of AppButtons"

This commit is contained in:
Chaohui Wang
2022-11-28 11:54:12 +00:00
committed by Android (Google) Code Review
3 changed files with 7 additions and 41 deletions

View File

@@ -21,23 +21,21 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import com.android.settingslib.applications.AppUtils import com.android.settingslib.applications.AppUtils
import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.widget.button.ActionButton import com.android.settingslib.spa.widget.button.ActionButton
import com.android.settingslib.spa.widget.button.ActionButtons import com.android.settingslib.spa.widget.button.ActionButtons
import com.android.settingslib.spaprivileged.model.app.isSystemModule
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
@Composable @Composable
fun AppButtons(packageInfoPresenter: PackageInfoPresenter) { fun AppButtons(packageInfoPresenter: PackageInfoPresenter) {
if (remember(packageInfoPresenter) { packageInfoPresenter.isMainlineModule() }) return
val presenter = remember { AppButtonsPresenter(packageInfoPresenter) } val presenter = remember { AppButtonsPresenter(packageInfoPresenter) }
if (!presenter.isAvailableFlow.collectAsStateWithLifecycle(initialValue = false).value) return
presenter.Dialogs() presenter.Dialogs()
ActionButtons(actionButtons = presenter.rememberActionsButtons().value) ActionButtons(actionButtons = presenter.rememberActionsButtons().value)
} }
private fun PackageInfoPresenter.isMainlineModule(): Boolean =
AppUtils.isMainlineModule(userPackageManager, packageName)
private class AppButtonsPresenter(private val packageInfoPresenter: PackageInfoPresenter) { private class AppButtonsPresenter(private val packageInfoPresenter: PackageInfoPresenter) {
private val appLaunchButton = AppLaunchButton(packageInfoPresenter) private val appLaunchButton = AppLaunchButton(packageInfoPresenter)
private val appInstallButton = AppInstallButton(packageInfoPresenter) private val appInstallButton = AppInstallButton(packageInfoPresenter)
@@ -46,15 +44,6 @@ private class AppButtonsPresenter(private val packageInfoPresenter: PackageInfoP
private val appClearButton = AppClearButton(packageInfoPresenter) private val appClearButton = AppClearButton(packageInfoPresenter)
private val appForceStopButton = AppForceStopButton(packageInfoPresenter) private val appForceStopButton = AppForceStopButton(packageInfoPresenter)
val isAvailableFlow = flow { emit(isAvailable()) }
private suspend fun isAvailable(): Boolean = withContext(Dispatchers.IO) {
!packageInfoPresenter.userPackageManager.isSystemModule(packageInfoPresenter.packageName) &&
!AppUtils.isMainlineModule(
packageInfoPresenter.userPackageManager, packageInfoPresenter.packageName
)
}
@Composable @Composable
fun rememberActionsButtons() = remember { fun rememberActionsButtons() = remember {
packageInfoPresenter.flow.map { packageInfo -> packageInfoPresenter.flow.map { packageInfo ->

View File

@@ -148,9 +148,7 @@ class PackageInfoPresenter(
private fun getPackageInfo() = private fun getPackageInfo() =
PackageManagers.getPackageInfoAsUser( PackageManagers.getPackageInfoAsUser(
packageName = packageName, packageName = packageName,
flags = PackageManager.MATCH_DISABLED_COMPONENTS or flags = PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.GET_PERMISSIONS,
PackageManager.GET_SIGNATURES or
PackageManager.GET_PERMISSIONS,
userId = userId, userId = userId,
) )
} }

View File

@@ -18,12 +18,8 @@ package com.android.settings.spa.app.appinfo
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.ModuleInfo
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.NameNotFoundException
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
@@ -33,16 +29,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.settingslib.applications.AppUtils import com.android.settingslib.applications.AppUtils
import com.android.settingslib.spa.testutils.delay import com.android.settingslib.spa.testutils.delay
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.stateIn
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.doThrow
import org.mockito.MockitoSession import org.mockito.MockitoSession
import org.mockito.Spy import org.mockito.Spy
import org.mockito.quality.Strictness import org.mockito.quality.Strictness
@@ -74,7 +67,6 @@ class AppButtonsTest {
whenever(packageInfoPresenter.context).thenReturn(context) whenever(packageInfoPresenter.context).thenReturn(context)
whenever(packageInfoPresenter.packageName).thenReturn(PACKAGE_NAME) whenever(packageInfoPresenter.packageName).thenReturn(PACKAGE_NAME)
whenever(packageInfoPresenter.userPackageManager).thenReturn(packageManager) whenever(packageInfoPresenter.userPackageManager).thenReturn(packageManager)
doThrow(NameNotFoundException()).`when`(packageManager).getModuleInfo(PACKAGE_NAME, 0)
whenever(packageManager.getPackageInfo(PACKAGE_NAME, 0)).thenReturn(PACKAGE_INFO) whenever(packageManager.getPackageInfo(PACKAGE_NAME, 0)).thenReturn(PACKAGE_INFO)
whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(false) whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(false)
} }
@@ -84,15 +76,6 @@ class AppButtonsTest {
mockSession.finishMocking() mockSession.finishMocking()
} }
@Test
fun isSystemModule_notDisplayed() {
doReturn(ModuleInfo()).`when`(packageManager).getModuleInfo(PACKAGE_NAME, 0)
setContent()
composeTestRule.onRoot().assertIsNotDisplayed()
}
@Test @Test
fun isMainlineModule_notDisplayed() { fun isMainlineModule_notDisplayed() {
whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(true) whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(true)
@@ -110,12 +93,8 @@ class AppButtonsTest {
} }
private fun setContent() { private fun setContent() {
whenever(packageInfoPresenter.flow).thenReturn(MutableStateFlow(PACKAGE_INFO))
composeTestRule.setContent { composeTestRule.setContent {
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
whenever(packageInfoPresenter.flow).thenReturn(flowOf(PACKAGE_INFO).stateIn(scope))
}
AppButtons(packageInfoPresenter) AppButtons(packageInfoPresenter)
} }