From 7adac0459c4b59956987c0dfd9ad8dcc40005a76 Mon Sep 17 00:00:00 2001 From: Mark Kim Date: Wed, 31 Jan 2024 17:50:42 +0000 Subject: [PATCH] Use a separated flag for archiving feature in Settings The new flag will replace the current PM-flag eventually, once they reach the same rollout status. Until then both flags are kept concurrently, to avoid a rollback of the feature. This is done to reduce risk and potentially enable an isolated rollback of Settings related logic, while keeping system logic intact. Additionally, fix bug by replacing `System.getProperty("pm.archiving.enabled")` to `SystemProperties.getBoolean("pm.archiving.enabled", false)` Test: InstalledAppCounterTest, AppButtonsTest, HibernationSwitchPreferenceTest Bug: 323164382 Change-Id: I44a41d6a43a12134c4e3aa5df8ad6a9eb91758d4 --- aconfig/settings_flag_declarations.aconfig | 7 +++++++ .../android/settings/applications/AppCounter.java | 10 +++++++++- .../android/settings/spa/app/appinfo/AppButtons.kt | 8 ++++---- .../settings/spa/app/appinfo/AppInfoSettings.kt | 12 +++++++----- .../spa/app/appinfo/HibernationSwitchPreference.kt | 7 +++++-- .../settings/spa/app/appinfo/PackageInfoPresenter.kt | 8 +++++--- .../app/appinfo/HibernationSwitchPreferenceTest.kt | 8 +++++--- 7 files changed, 42 insertions(+), 18 deletions(-) diff --git a/aconfig/settings_flag_declarations.aconfig b/aconfig/settings_flag_declarations.aconfig index 56c4b321cba..36f104c2fe6 100644 --- a/aconfig/settings_flag_declarations.aconfig +++ b/aconfig/settings_flag_declarations.aconfig @@ -13,3 +13,10 @@ flag { description: "Enabling will provide an explicit package name for Intent to update mainline modules" bug: "278987474" } + +flag { + name: "app_archiving" + namespace: "android_settings" + description: "Feature flag to enable the archiving feature." + bug: "323164382" +} diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java index d5369324279..2b1e47eaf23 100644 --- a/src/com/android/settings/applications/AppCounter.java +++ b/src/com/android/settings/applications/AppCounter.java @@ -22,12 +22,15 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.UserInfo; import android.os.AsyncTask; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import com.android.settings.flags.Flags; + import java.util.List; public abstract class AppCounter extends AsyncTask { @@ -54,7 +57,7 @@ public abstract class AppCounter extends AsyncTask { for (UserInfo user : mUm.getProfiles(UserHandle.myUserId())) { long flags = PackageManager.GET_DISABLED_COMPONENTS | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS - | (mFf.archiving() ? PackageManager.MATCH_ARCHIVED_PACKAGES : 0) + | (isArchivingEnabled() ? PackageManager.MATCH_ARCHIVED_PACKAGES : 0) | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0); ApplicationInfoFlags infoFlags = ApplicationInfoFlags.of(flags); final List list = @@ -68,6 +71,11 @@ public abstract class AppCounter extends AsyncTask { return count; } + private boolean isArchivingEnabled() { + return mFf.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false) + || Flags.appArchiving(); + } + @Override protected void onPostExecute(Integer count) { onCountComplete(count); diff --git a/src/com/android/settings/spa/app/appinfo/AppButtons.kt b/src/com/android/settings/spa/app/appinfo/AppButtons.kt index dcce1d91fc2..3d9c4b185d1 100644 --- a/src/com/android/settings/spa/app/appinfo/AppButtons.kt +++ b/src/com/android/settings/spa/app/appinfo/AppButtons.kt @@ -17,8 +17,8 @@ package com.android.settings.spa.app.appinfo import android.content.pm.ApplicationInfo -import android.content.pm.FeatureFlags -import android.content.pm.FeatureFlagsImpl +import android.content.pm.FeatureFlags as PmFeatureFlags +import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -34,7 +34,7 @@ import kotlinx.coroutines.flow.MutableStateFlow fun AppButtons( packageInfoPresenter: PackageInfoPresenter, isHibernationSwitchEnabledStateFlow: MutableStateFlow, - featureFlags: FeatureFlags = FeatureFlagsImpl() + featureFlags: PmFeatureFlags = PmFeatureFlagsImpl() ) { if (remember(packageInfoPresenter) { packageInfoPresenter.isMainlineModule() }) return val presenter = remember { @@ -53,7 +53,7 @@ private fun PackageInfoPresenter.isMainlineModule(): Boolean = private class AppButtonsPresenter( private val packageInfoPresenter: PackageInfoPresenter, isHibernationSwitchEnabledStateFlow: MutableStateFlow, - private val featureFlags: FeatureFlags + private val featureFlags: PmFeatureFlags ) { private val appLaunchButton = AppLaunchButton(packageInfoPresenter) private val appInstallButton = AppInstallButton(packageInfoPresenter) diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index dba61848501..695e114a987 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -18,9 +18,8 @@ package com.android.settings.spa.app.appinfo import android.app.settings.SettingsEnums import android.content.pm.ApplicationInfo -import android.content.pm.FeatureFlags -import android.content.pm.FeatureFlagsImpl import android.os.Bundle +import android.os.SystemProperties import android.os.UserHandle import android.util.FeatureFlagUtils import androidx.compose.runtime.Composable @@ -51,6 +50,8 @@ import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spaprivileged.model.app.toRoute import com.android.settingslib.spaprivileged.template.app.AppInfoProvider import kotlinx.coroutines.flow.MutableStateFlow +import android.content.pm.FeatureFlags as PmFeatureFlags +import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl private const val PACKAGE_NAME = "packageName" private const val USER_ID = "userId" @@ -121,7 +122,7 @@ object AppInfoSettingsProvider : SettingsPageProvider { @Composable private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle() - val featureFlags: FeatureFlags = FeatureFlagsImpl() + val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl() RegularScaffold( title = stringResource(R.string.application_info_label), actions = { @@ -177,5 +178,6 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { } } -fun isArchivingEnabled(featureFlags: FeatureFlags) = - featureFlags.archiving() || "true" == System.getProperty("pm.archiving.enabled") +fun isArchivingEnabled(featureFlags: PmFeatureFlags) = + featureFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false) + || Flags.appArchiving() \ No newline at end of file diff --git a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt index 4f472662120..86d7f445090 100644 --- a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt +++ b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt @@ -22,8 +22,9 @@ import android.app.AppOpsManager.MODE_IGNORED import android.app.AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED import android.content.Context import android.content.pm.ApplicationInfo -import android.content.pm.Flags +import android.content.pm.Flags as PmFlags import android.os.Build +import android.os.SystemProperties import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UNKNOWN import android.provider.DeviceConfig @@ -36,6 +37,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED import com.android.settings.Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS +import com.android.settings.flags.Flags import com.android.settingslib.spa.framework.compose.OverridableFlow import com.android.settingslib.spa.widget.preference.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel @@ -91,7 +93,8 @@ fun HibernationSwitchPreference( } private fun isArchivingEnabled() = - Flags.archiving() || "true" == System.getProperty("pm.archiving.enabled") + PmFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false) + || Flags.appArchiving() private class HibernationSwitchPresenter(context: Context, private val app: ApplicationInfo) { private val appOpsManager = context.appOpsManager diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt index 230ccb9883b..81abae5a3e0 100644 --- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt +++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt @@ -20,14 +20,16 @@ import android.app.settings.SettingsEnums import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.content.pm.FeatureFlags -import android.content.pm.FeatureFlagsImpl +import android.content.pm.FeatureFlags as PmFeatureFlags +import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.UserHandle import android.util.Log import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable +import com.android.settings.flags.FeatureFlags +import com.android.settings.flags.FeatureFlagsImpl import com.android.settings.overlay.FeatureFactory.Companion.featureFactory import com.android.settings.spa.app.startUninstallActivity import com.android.settingslib.spa.framework.compose.LocalNavController @@ -60,7 +62,7 @@ class PackageInfoPresenter( val userId: Int, private val coroutineScope: CoroutineScope, private val packageManagers: IPackageManagers = PackageManagers, - private val featureFlags: FeatureFlags = FeatureFlagsImpl(), + private val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl(), ) { private val metricsFeatureProvider = featureFactory.metricsFeatureProvider private val userHandle = UserHandle.of(userId) diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt index cc2c1e106e1..b61e3a9fd7c 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt @@ -24,8 +24,9 @@ import android.app.AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED import android.apphibernation.AppHibernationManager import android.content.Context import android.content.pm.ApplicationInfo -import android.content.pm.Flags +import android.content.pm.Flags as PmFlags import android.os.Build +import android.os.SystemProperties import android.permission.PermissionControllerManager import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_ELIGIBLE import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM @@ -48,6 +49,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R import com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED import com.android.settings.Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS +import com.android.settings.flags.Flags import com.android.settings.testutils.TestDeviceConfig import com.android.settings.testutils.mockAsUser import com.android.settingslib.spaprivileged.framework.common.appHibernationManager @@ -161,8 +163,8 @@ class HibernationSwitchPreferenceTest { } private fun isArchivingEnabled() = - Flags.archiving() || "true" == System.getProperty("pm.archiving.enabled") - + PmFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false) + || Flags.appArchiving() @Test fun `An app targets Q with ops mode default when hibernation targets pre S - not exempted`() { mockOpsMode(MODE_DEFAULT)