Merge "Stop app when toggling backcompat setting" into main

This commit is contained in:
Treehugger Robot
2025-03-02 16:59:40 -08:00
committed by Android (Google) Code Review
4 changed files with 68 additions and 7 deletions

View File

@@ -13148,7 +13148,11 @@ Data usage charges may apply.</string>
<string name="page_agnostic_notification_action">Read more</string>
<string name= "enable_16k_app_compat_title">Run app with page size compat mode</string>
<string name= "enable_16k_app_compat_details">App will be run in page size compatibility mode on 16 KB device when toggled.</string>
<string name= "enable_16k_app_compat_details">App will be forced stopped and run in page size compatibility mode on 16 KB device when toggled.</string>
<string name="stop_app_dlg_title">Stop app?</string>
<!-- [CHAR LIMIT=200] Manage applications, text for dialog when killing persistent apps-->
<string name="stop_app_dlg_text">Application will be stopped to apply page size compat setting.</string>
<!-- DSU Loader. Do not translate. -->

View File

@@ -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)) {

View File

@@ -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();
}
}

View File

@@ -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)
}