Display App installed in other user in All Apps
Only for admin user. Also clean up unused getInstallationStatus(). Fix: 277299765 Test: Manually with All Apps when multiple users is on Test: Unit test Change-Id: I4de681c101a605e3517dcd8765bf7a95d1b76417
This commit is contained in:
@@ -986,17 +986,6 @@ public final class Utils extends com.android.settingslib.Utils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the resource id to represent the install status for an app
|
|
||||||
*/
|
|
||||||
@StringRes
|
|
||||||
public static int getInstallationStatus(ApplicationInfo info) {
|
|
||||||
if ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
|
|
||||||
return R.string.not_installed;
|
|
||||||
}
|
|
||||||
return info.enabled ? R.string.installed : R.string.disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isVolumeValid(VolumeInfo volume) {
|
private static boolean isVolumeValid(VolumeInfo volume) {
|
||||||
return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
|
return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
|
||||||
&& volume.isMountedReadable();
|
&& volume.isMountedReadable();
|
||||||
|
@@ -38,6 +38,7 @@ import com.android.settingslib.spa.widget.preference.PreferenceModel
|
|||||||
import com.android.settingslib.spa.widget.ui.SpinnerOption
|
import com.android.settingslib.spa.widget.ui.SpinnerOption
|
||||||
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||||
|
import com.android.settingslib.spaprivileged.model.app.installed
|
||||||
import com.android.settingslib.spaprivileged.template.app.AppList
|
import com.android.settingslib.spaprivileged.template.app.AppList
|
||||||
import com.android.settingslib.spaprivileged.template.app.AppListInput
|
import com.android.settingslib.spaprivileged.template.app.AppListInput
|
||||||
import com.android.settingslib.spaprivileged.template.app.AppListItem
|
import com.android.settingslib.spaprivileged.template.app.AppListItem
|
||||||
@@ -75,6 +76,7 @@ fun AllAppListPage(
|
|||||||
title = stringResource(R.string.all_apps),
|
title = stringResource(R.string.all_apps),
|
||||||
listModel = rememberContext(::AllAppListModel),
|
listModel = rememberContext(::AllAppListModel),
|
||||||
showInstantApps = true,
|
showInstantApps = true,
|
||||||
|
matchAnyUserForAdmin = true,
|
||||||
moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) },
|
moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) },
|
||||||
appList = appList,
|
appList = appList,
|
||||||
)
|
)
|
||||||
@@ -133,8 +135,13 @@ class AllAppListModel(
|
|||||||
return remember {
|
return remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
storageSummary.value +
|
storageSummary.value +
|
||||||
when (isDisabled(record)) {
|
when {
|
||||||
true -> System.lineSeparator() + context.getString(R.string.disabled)
|
!record.app.installed -> {
|
||||||
|
System.lineSeparator() + context.getString(R.string.not_installed)
|
||||||
|
}
|
||||||
|
isDisabled(record) -> {
|
||||||
|
System.lineSeparator() + context.getString(R.string.disabled)
|
||||||
|
}
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,8 +30,10 @@ import com.android.settings.notification.app.AppNotificationSettings
|
|||||||
import com.android.settings.spa.notification.AppNotificationRepository
|
import com.android.settings.spa.notification.AppNotificationRepository
|
||||||
import com.android.settings.spa.notification.IAppNotificationRepository
|
import com.android.settings.spa.notification.IAppNotificationRepository
|
||||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||||
|
import com.android.settingslib.spa.framework.compose.stateOf
|
||||||
import com.android.settingslib.spa.widget.preference.Preference
|
import com.android.settingslib.spa.widget.preference.Preference
|
||||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||||
|
import com.android.settingslib.spaprivileged.model.app.installed
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
@@ -53,6 +55,7 @@ fun AppNotificationPreference(
|
|||||||
override val summary = summaryFlow.collectAsStateWithLifecycle(
|
override val summary = summaryFlow.collectAsStateWithLifecycle(
|
||||||
initialValue = stringResource(R.string.summary_placeholder)
|
initialValue = stringResource(R.string.summary_placeholder)
|
||||||
)
|
)
|
||||||
|
override val enabled = stateOf(app.installed)
|
||||||
override val onClick = { navigateToAppNotificationSettings(context, app) }
|
override val onClick = { navigateToAppNotificationSettings(context, app) }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -141,7 +141,9 @@ class PackageInfoPresenter(
|
|||||||
private fun getPackageInfo() =
|
private fun getPackageInfo() =
|
||||||
packageManagers.getPackageInfoAsUser(
|
packageManagers.getPackageInfoAsUser(
|
||||||
packageName = packageName,
|
packageName = packageName,
|
||||||
flags = PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.GET_PERMISSIONS,
|
flags = PackageManager.MATCH_ANY_USER or
|
||||||
|
PackageManager.MATCH_DISABLED_COMPONENTS or
|
||||||
|
PackageManager.GET_PERMISSIONS,
|
||||||
userId = userId,
|
userId = userId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settingslib.spaprivileged.model.app.AppOpsController
|
import com.android.settingslib.spaprivileged.model.app.AppOpsController
|
||||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||||
|
import com.android.settingslib.spaprivileged.model.app.installed
|
||||||
import com.android.settingslib.spaprivileged.model.app.userId
|
import com.android.settingslib.spaprivileged.model.app.userId
|
||||||
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel
|
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel
|
||||||
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
|
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
|
||||||
@@ -67,11 +68,12 @@ class PictureInPictureListModel(private val context: Context) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun transformItem(app: ApplicationInfo): PictureInPictureRecord {
|
override fun transformItem(app: ApplicationInfo): PictureInPictureRecord {
|
||||||
val packageInfo =
|
|
||||||
packageManager.getPackageInfoAsUser(app.packageName, GET_ACTIVITIES_FLAGS, app.userId)
|
|
||||||
return createPictureInPictureRecord(
|
return createPictureInPictureRecord(
|
||||||
app = app,
|
app = app,
|
||||||
isSupport = packageInfo.supportsPictureInPicture(),
|
isSupport = app.installed &&
|
||||||
|
packageManager
|
||||||
|
.getPackageInfoAsUser(app.packageName, GET_ACTIVITIES_FLAGS, app.userId)
|
||||||
|
.supportsPictureInPicture(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -160,30 +160,6 @@ public class UtilsTest {
|
|||||||
Utils.maybeInitializeVolume(storageManager, new Bundle());
|
Utils.maybeInitializeVolume(storageManager, new Bundle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
|
|
||||||
assertThat(Utils.getInstallationStatus(new ApplicationInfo()))
|
|
||||||
.isEqualTo(R.string.not_installed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getInstallationStatus_enabled_shouldReturnInstalled() {
|
|
||||||
final ApplicationInfo info = new ApplicationInfo();
|
|
||||||
info.flags = ApplicationInfo.FLAG_INSTALLED;
|
|
||||||
info.enabled = true;
|
|
||||||
|
|
||||||
assertThat(Utils.getInstallationStatus(info)).isEqualTo(R.string.installed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getInstallationStatus_disabled_shouldReturnDisabled() {
|
|
||||||
final ApplicationInfo info = new ApplicationInfo();
|
|
||||||
info.flags = ApplicationInfo.FLAG_INSTALLED;
|
|
||||||
info.enabled = false;
|
|
||||||
|
|
||||||
assertThat(Utils.getInstallationStatus(info)).isEqualTo(R.string.disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isProfileOrDeviceOwner_deviceOwnerApp_returnTrue() {
|
public void isProfileOrDeviceOwner_deviceOwnerApp_returnTrue() {
|
||||||
when(mDevicePolicyManager.isDeviceOwnerAppOnAnyUser(PACKAGE_NAME)).thenReturn(true);
|
when(mDevicePolicyManager.isDeviceOwnerAppOnAnyUser(PACKAGE_NAME)).thenReturn(true);
|
||||||
|
@@ -147,6 +147,7 @@ class AllAppListTest {
|
|||||||
val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
|
val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
|
||||||
val disabledApp = ApplicationInfo().apply {
|
val disabledApp = ApplicationInfo().apply {
|
||||||
packageName = PACKAGE_NAME
|
packageName = PACKAGE_NAME
|
||||||
|
flags = ApplicationInfo.FLAG_INSTALLED
|
||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +160,23 @@ class AllAppListTest {
|
|||||||
assertThat(summaryState.value).isEqualTo("$SUMMARY${System.lineSeparator()}Disabled")
|
assertThat(summaryState.value).isEqualTo("$SUMMARY${System.lineSeparator()}Disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun allAppListModel_getSummaryWhenNotInstalled() {
|
||||||
|
val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
|
||||||
|
val notInstalledApp = ApplicationInfo().apply {
|
||||||
|
packageName = PACKAGE_NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var summaryState: State<String>
|
||||||
|
composeTestRule.setContent {
|
||||||
|
summaryState =
|
||||||
|
listModel.getSummary(option = 0, record = AppRecordWithSize(app = notInstalledApp))
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(summaryState.value)
|
||||||
|
.isEqualTo("$SUMMARY${System.lineSeparator()}Not installed for this user")
|
||||||
|
}
|
||||||
|
|
||||||
private fun getAppListInput(): AppListInput<AppRecordWithSize> {
|
private fun getAppListInput(): AppListInput<AppRecordWithSize> {
|
||||||
lateinit var input: AppListInput<AppRecordWithSize>
|
lateinit var input: AppListInput<AppRecordWithSize>
|
||||||
composeTestRule.setContent {
|
composeTestRule.setContent {
|
||||||
@@ -192,6 +210,7 @@ class AllAppListTest {
|
|||||||
const val SUMMARY = "Summary"
|
const val SUMMARY = "Summary"
|
||||||
val APP = ApplicationInfo().apply {
|
val APP = ApplicationInfo().apply {
|
||||||
packageName = PACKAGE_NAME
|
packageName = PACKAGE_NAME
|
||||||
|
flags = ApplicationInfo.FLAG_INSTALLED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import android.content.pm.ApplicationInfo
|
|||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.test.assertIsDisplayed
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
|
import androidx.compose.ui.test.assertIsNotEnabled
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
import androidx.compose.ui.test.onRoot
|
import androidx.compose.ui.test.onRoot
|
||||||
@@ -72,7 +73,7 @@ class AppNotificationPreferenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun title_displayed() {
|
fun title_displayed() {
|
||||||
setContent()
|
setContent(APP)
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(context.getString(R.string.notifications_label))
|
composeTestRule.onNodeWithText(context.getString(R.string.notifications_label))
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
@@ -80,14 +81,25 @@ class AppNotificationPreferenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun summary_displayed() {
|
fun summary_displayed() {
|
||||||
setContent()
|
setContent(APP)
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
|
composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenNotInstalled_disable() {
|
||||||
|
setContent(ApplicationInfo().apply {
|
||||||
|
packageName = PACKAGE_NAME
|
||||||
|
uid = UID
|
||||||
|
})
|
||||||
|
|
||||||
|
composeTestRule.onNodeWithText(context.getString(R.string.notifications_label))
|
||||||
|
.assertIsNotEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onClick_startActivity() {
|
fun onClick_startActivity() {
|
||||||
setContent()
|
setContent(APP)
|
||||||
|
|
||||||
composeTestRule.onRoot().performClick()
|
composeTestRule.onRoot().performClick()
|
||||||
composeTestRule.delay()
|
composeTestRule.delay()
|
||||||
@@ -102,10 +114,10 @@ class AppNotificationPreferenceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setContent() {
|
private fun setContent(app: ApplicationInfo) {
|
||||||
composeTestRule.setContent {
|
composeTestRule.setContent {
|
||||||
CompositionLocalProvider(LocalContext provides context) {
|
CompositionLocalProvider(LocalContext provides context) {
|
||||||
AppNotificationPreference(app = APP, repository = repository)
|
AppNotificationPreference(app = app, repository = repository)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +128,7 @@ class AppNotificationPreferenceTest {
|
|||||||
val APP = ApplicationInfo().apply {
|
val APP = ApplicationInfo().apply {
|
||||||
packageName = PACKAGE_NAME
|
packageName = PACKAGE_NAME
|
||||||
uid = UID
|
uid = UID
|
||||||
|
flags = ApplicationInfo.FLAG_INSTALLED
|
||||||
}
|
}
|
||||||
const val SUMMARY = "Summary"
|
const val SUMMARY = "Summary"
|
||||||
}
|
}
|
||||||
|
@@ -167,6 +167,7 @@ class PictureInPictureTest {
|
|||||||
const val PICTURE_IN_PICTURE_PACKAGE_NAME = "picture.in.picture.package.name"
|
const val PICTURE_IN_PICTURE_PACKAGE_NAME = "picture.in.picture.package.name"
|
||||||
val PICTURE_IN_PICTURE_APP = ApplicationInfo().apply {
|
val PICTURE_IN_PICTURE_APP = ApplicationInfo().apply {
|
||||||
packageName = PICTURE_IN_PICTURE_PACKAGE_NAME
|
packageName = PICTURE_IN_PICTURE_PACKAGE_NAME
|
||||||
|
flags = ApplicationInfo.FLAG_INSTALLED
|
||||||
}
|
}
|
||||||
val PICTURE_IN_PICTURE_PACKAGE_INFO = PackageInfo().apply {
|
val PICTURE_IN_PICTURE_PACKAGE_INFO = PackageInfo().apply {
|
||||||
packageName = PICTURE_IN_PICTURE_PACKAGE_NAME
|
packageName = PICTURE_IN_PICTURE_PACKAGE_NAME
|
||||||
|
Reference in New Issue
Block a user