diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4c91c2a655c..a5ba4846ad2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13148,7 +13148,11 @@ Data usage charges may apply.
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)
}