diff --git a/lawnchair/AndroidManifest.xml b/lawnchair/AndroidManifest.xml
index 5d56727bb4b..904818d411a 100644
--- a/lawnchair/AndroidManifest.xml
+++ b/lawnchair/AndroidManifest.xml
@@ -20,7 +20,7 @@
xmlns:tools="http://schemas.android.com/tools">
-
+
@@ -29,11 +29,12 @@
-
-
-
-
-
+
+
+
+
+
+
diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index 8a590ba89ce..d141e29c80d 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -558,6 +558,13 @@
Vertical inset (Bottom)
+
+ Pause
+ Pause %1$s?
+ Notifications for %1$s will be paused
+ App paused
+ %1$s was directly paused from the launcher
+ Pause app
Dock icons
Bottom padding
diff --git a/lawnchair/src/app/lawnchair/LawnchairLauncher.kt b/lawnchair/src/app/lawnchair/LawnchairLauncher.kt
index 63cd9a4fe92..fabcf5e095d 100644
--- a/lawnchair/src/app/lawnchair/LawnchairLauncher.kt
+++ b/lawnchair/src/app/lawnchair/LawnchairLauncher.kt
@@ -235,7 +235,13 @@ class LawnchairLauncher : QuickstepLauncher() {
}
override fun getSupportedShortcuts(): Stream> =
- Stream.concat(super.getSupportedShortcuts(), Stream.of(LawnchairShortcut.UNINSTALL, LawnchairShortcut.CUSTOMIZE))
+ Stream.concat(
+ super.getSupportedShortcuts(),
+ Stream.concat(
+ Stream.of(LawnchairShortcut.UNINSTALL, LawnchairShortcut.CUSTOMIZE),
+ if (LawnchairApp.isRecentsEnabled) Stream.of(LawnchairShortcut.PAUSE_APPS) else Stream.empty(),
+ ),
+ )
override fun updateTheme() {
if (themeProvider.colorScheme != colorScheme) {
diff --git a/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt b/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt
index 91974dffad6..2e170de3917 100644
--- a/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt
+++ b/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt
@@ -1,13 +1,18 @@
package app.lawnchair.ui.popup
+import android.annotation.SuppressLint
+import android.app.AlertDialog
+import android.app.AppGlobals
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
+import android.content.pm.SuspendDialogInfo
import android.net.Uri
import android.os.UserHandle
+import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.compose.foundation.layout.PaddingValues
@@ -65,6 +70,15 @@ class LawnchairShortcut {
}
UnInstall(activity, itemInfo, view)
}
+
+ val PAUSE_APPS = SystemShortcut.Factory { activity: LawnchairLauncher, itemInfo: ItemInfo, originalView: View ->
+ val targetCmp = itemInfo.targetComponent
+ val packageName = targetCmp?.packageName ?: return@Factory null
+
+ if (PackageManagerHelper(activity).isAppSuspended(packageName, itemInfo.user)) return@Factory null
+
+ PauseApps(activity, itemInfo, originalView)
+ }
}
class Customize(
@@ -97,6 +111,59 @@ class LawnchairShortcut {
}
}
+ class PauseApps(
+ target: LawnchairLauncher,
+ itemInfo: ItemInfo,
+ originalView: View,
+ ) : SystemShortcut(
+ R.drawable.ic_hourglass_top,
+ R.string.paused_apps_drop_target_label,
+ target,
+ itemInfo,
+ originalView,
+ ) {
+ @SuppressLint("NewApi")
+ override fun onClick(view: View) {
+ val context = view.context
+ val appLabel = PackageManagerHelper(context).getApplicationInfo(
+ mItemInfo.targetComponent?.packageName ?: "",
+ mItemInfo.user,
+ 0,
+ )?.let {
+ context.packageManager.getApplicationLabel(
+ it,
+ )
+ }
+ AlertDialog.Builder(context)
+ .setIcon(R.drawable.ic_hourglass_top)
+ .setTitle(context.getString(R.string.pause_apps_dialog_title, appLabel))
+ .setMessage(context.getString(R.string.pause_apps_dialog_message, appLabel))
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(R.string.pause) { _, _ ->
+ try {
+ AppGlobals.getPackageManager().setPackagesSuspendedAsUser(
+ arrayOf(mItemInfo.targetComponent?.packageName ?: ""),
+ true, null, null,
+ SuspendDialogInfo.Builder()
+ .setIcon(R.drawable.ic_hourglass_top)
+ .setTitle(R.string.paused_apps_dialog_title)
+ .setMessage(R.string.paused_apps_dialog_message)
+ .setNeutralButtonAction(SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND)
+ .build(),
+ 0,
+ context.opPackageName,
+ context.userId,
+ mItemInfo.user.identifier,
+ )
+ } catch (e: Throwable) {
+ Log.e("LawnchairShortcut", "Failed to pause app", e)
+ }
+ }
+ .show()
+ AbstractFloatingView.closeAllOpenViews(mTarget)
+ }
+ }
+
class UnInstall(private var target: BaseDraggingActivity?, private var itemInfo: ItemInfo?, originalView: View?) :
SystemShortcut(
R.drawable.ic_uninstall_no_shadow,