diff --git a/res/values/strings.xml b/res/values/strings.xml index 823b87c687c..e91df31af34 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13097,7 +13097,11 @@ Read more Run app with page size compat mode - App will be run in page size compatibility mode on 16 KB device when toggled. + App will be forced stopped and run in page size compatibility mode on 16 KB device when toggled. + + Stop app? + + Application will be stopped to apply page size compat setting. diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt index 78fb8df123b..1feab551e11 100644 --- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt +++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt @@ -170,7 +170,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) { InteractAcrossProfilesDetailsPreference(app) AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app) WriteSystemPreferencesAppListProvider.InfoPageEntryItem(app) - Enable16KbAppCompatPreference(app) + Enable16KbAppCompatPreference(app, packageInfoPresenter) } Category(title = stringResource(R.string.app_install_details_group_title)) { diff --git a/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt b/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt index b6606cf881a..6201c83a64f 100644 --- a/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt +++ b/src/com/android/settings/spa/app/appinfo/Enable16KbAppCompatPreference.kt @@ -16,8 +16,12 @@ package com.android.settings.spa.app.appinfo +import android.app.AlertDialog +import android.app.settings.SettingsEnums import android.content.Context +import android.content.DialogInterface import android.content.pm.ApplicationInfo +import android.os.UserManager import android.util.Log import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -26,17 +30,23 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.development.Enable16kUtils import com.android.settings.flags.Flags +import com.android.settingslib.RestrictedLockUtils +import com.android.settingslib.RestrictedLockUtilsInternal import com.android.settingslib.spa.framework.compose.OverridableFlow +import com.android.settingslib.spa.widget.dialog.AlertDialogButton +import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter import com.android.settingslib.spa.widget.preference.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel +import com.android.settingslib.spaprivileged.model.app.userId import kotlinx.coroutines.flow.flow @Composable fun Enable16KbAppCompatPreference( - app: ApplicationInfo + app: ApplicationInfo, + packageInfoPresenter: PackageInfoPresenter ) { val context = LocalContext.current - val presenter = remember(app) { Enable16KbAppCompatSwitchPresenter(context, app) } + val presenter = remember(app) { Enable16KbAppCompatSwitchPresenter(context, app, packageInfoPresenter) } if (!presenter.isAvailable()) return val isCheckedState = presenter.isCheckedFlow.collectAsStateWithLifecycle(initialValue = null) @@ -58,7 +68,9 @@ fun Enable16KbAppCompatPreference( }) } -private class Enable16KbAppCompatSwitchPresenter(context: Context, private val app: ApplicationInfo) { + +private class Enable16KbAppCompatSwitchPresenter(private val context: Context, private val app: ApplicationInfo, + private val packageInfoPresenter: PackageInfoPresenter) { private val packageManager = context.packageManager fun isAvailable(): Boolean { return Enable16kUtils.isUsing16kbPages() && Flags.pageSizeAppCompatSetting() @@ -69,13 +81,48 @@ private class Enable16KbAppCompatSwitchPresenter(context: Context, private val a }) val isCheckedFlow = isChecked.flow + fun onCheckedChange(newChecked: Boolean) { try { - packageManager.setPageSizeAppCompatFlagsSettingsOverride(app.packageName, newChecked) - isChecked.override(newChecked) + getForceStopRestriction(app)?.let { admin -> + RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, admin) + return + } + showDialog(newChecked) } catch (e: RuntimeException) { Log.e("Enable16KbAppCompat", "Failed to set" + "setPageSizeAppCompatModeSettingsOverride", e); } } + + fun updatePageSizeCompat(newChecked: Boolean) { + packageManager.setPageSizeAppCompatFlagsSettingsOverride(app.packageName, newChecked) + isChecked.override(newChecked) + packageInfoPresenter.stopPackage() + } + + fun getForceStopRestriction(app: ApplicationInfo): RestrictedLockUtils.EnforcedAdmin? = when { + packageManager.isPackageStateProtected(app.packageName, app.userId) -> { + RestrictedLockUtilsInternal.getDeviceOwner(context) ?: RestrictedLockUtils.EnforcedAdmin() + } + + else -> RestrictedLockUtilsInternal.checkIfRestrictionEnforced( + context, UserManager.DISALLOW_APPS_CONTROL, app.userId + ) + } + + fun showDialog(newChecked: Boolean) { + // Uses the same string from 'Force Stop' action button. + val builder = + AlertDialog.Builder(context) + .setTitle(R.string.stop_app_dlg_title) + .setMessage(R.string.stop_app_dlg_text) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.okay, DialogInterface.OnClickListener { dialog, _ -> + updatePageSizeCompat(newChecked) + dialog.dismiss() + }) + .create(); + builder.show(); + } } diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt index 36fe93e2f27..81073cdd94b 100644 --- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt +++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt @@ -185,6 +185,16 @@ class PackageInfoPresenter( } } + /* stops application without durable effects of the full-scale "forec stop" */ + fun stopPackage() { + requireAuthAndExecute { + coroutineScope.launch(Dispatchers.Default) { + Log.d(TAG, "Stopping package $packageName for user") + context.activityManager.stopPackageForUser(packageName) + } + } + } + fun logAction(category: Int) { metricsFeatureProvider.action(context, category, packageName) }