diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index 971919463d..846a1fa016 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -239,4 +239,6 @@
Page %1$d of %2$d
At a Glance
Fri, Mar 3
+ Incompatible System Integration
+ Your device is configured to have system gestures (known as Quickstep) provided by %1$s, but this version of %1$s is not compatible with your Android version. To continue using your device, please uninstall %1$s updates or unset %1$s as a system gestures provider.
diff --git a/lawnchair/src/app/lawnchair/LawnchairApp.kt b/lawnchair/src/app/lawnchair/LawnchairApp.kt
index 137adf6634..e464b70a04 100644
--- a/lawnchair/src/app/lawnchair/LawnchairApp.kt
+++ b/lawnchair/src/app/lawnchair/LawnchairApp.kt
@@ -25,10 +25,23 @@ import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.requiredWidth
+import androidx.compose.material3.Button
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.Text
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
import app.lawnchair.preferences.PreferenceManager
+import app.lawnchair.ui.AlertBottomSheetContent
+import app.lawnchair.ui.preferences.openAppInfo
import app.lawnchair.util.restartLauncher
+import app.lawnchair.views.ComposeBottomSheet
import com.android.launcher3.BuildConfig
import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.Launcher
+import com.android.launcher3.R
import com.android.quickstep.RecentsActivity
import com.android.systemui.shared.system.QuickStepContract
import java.io.File
@@ -36,7 +49,9 @@ import java.io.File
class LawnchairApp : Application() {
val activityHandler = ActivityHandler()
- private val recentsEnabled by lazy { checkRecentsComponent() }
+ private val compatible = Build.VERSION.SDK_INT in BuildConfig.QUICKSTEP_MIN_SDK..BuildConfig.QUICKSTEP_MAX_SDK
+ private val isRecentsComponent by lazy { checkRecentsComponent() }
+ private val recentsEnabled get() = compatible && isRecentsComponent
internal var accessibilityService: LawnchairAccessibilityService? = null
override fun onCreate() {
@@ -121,11 +136,6 @@ class LawnchairApp : Application() {
}
private fun checkRecentsComponent(): Boolean {
- if (Build.VERSION.SDK_INT !in BuildConfig.QUICKSTEP_MIN_SDK..BuildConfig.QUICKSTEP_MAX_SDK) {
- Log.d(TAG, "API ${Build.VERSION.SDK_INT} unsupported, disabling recents")
- return false
- }
-
val resId = resources.getIdentifier("config_recentsComponentName", "string", "android")
if (resId == 0) {
Log.d(TAG, "config_recentsComponentName not found, disabling recents")
@@ -172,6 +182,40 @@ class LawnchairApp : Application() {
@JvmStatic
val isRecentsEnabled: Boolean
get() = instance?.recentsEnabled == true
+
+ fun Launcher.showQuickstepWarningIfNecessary() {
+ val launcher = this
+ if (!lawnchairApp.isRecentsComponent || isRecentsEnabled) return
+ ComposeBottomSheet.show(this) {
+ AlertBottomSheetContent(
+ title = { Text(text = stringResource(id = R.string.quickstep_incompatible)) },
+ text = {
+ val description = stringResource(
+ id = R.string.quickstep_incompatible_description,
+ stringResource(id = R.string.derived_app_name),
+ Build.VERSION.RELEASE
+ )
+ Text(text = description)
+ },
+ buttons = {
+ OutlinedButton(
+ onClick = {
+ openAppInfo(launcher)
+ close(true)
+ }
+ ) {
+ Text(text = stringResource(id = R.string.app_info_drop_target_label))
+ }
+ Spacer(modifier = Modifier.requiredWidth(8.dp))
+ Button(
+ onClick = { close(true) }
+ ) {
+ Text(text = stringResource(id = android.R.string.ok))
+ }
+ }
+ )
+ }
+ }
}
}
diff --git a/lawnchair/src/app/lawnchair/LawnchairLauncher.kt b/lawnchair/src/app/lawnchair/LawnchairLauncher.kt
index 77d5c3ae18..9f63b4d393 100644
--- a/lawnchair/src/app/lawnchair/LawnchairLauncher.kt
+++ b/lawnchair/src/app/lawnchair/LawnchairLauncher.kt
@@ -39,6 +39,7 @@ import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryController
import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import app.lawnchair.LawnchairApp.Companion.showQuickstepWarningIfNecessary
import app.lawnchair.gestures.GestureController
import app.lawnchair.nexuslauncher.OverlayCallbackImpl
import app.lawnchair.preferences.PreferenceManager
@@ -224,6 +225,8 @@ class LawnchairLauncher : QuickstepLauncher(), LifecycleOwner,
}
colorScheme = themeProvider.colorScheme
+
+ showQuickstepWarningIfNecessary()
}
override fun setupViews() {
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/PreferencesDashboard.kt b/lawnchair/src/app/lawnchair/ui/preferences/PreferencesDashboard.kt
index 734821f1c8..ca3fc7fa2e 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/PreferencesDashboard.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/PreferencesDashboard.kt
@@ -124,7 +124,7 @@ fun PreferencesOverflowMenu() {
}
}
-private fun openAppInfo(context: Context) {
+fun openAppInfo(context: Context) {
val launcherApps = context.getSystemService()
val componentName = ComponentName(context, LawnchairLauncher::class.java)
launcherApps?.startAppDetailsActivity(componentName, Process.myUserHandle(), null, null)
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 61a7c5c156..881c40b44b 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -135,6 +135,7 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
+import app.lawnchair.LawnchairApp;
import app.lawnchair.icons.shape.IconShapeManager;
import app.lawnchair.theme.color.ColorTokens;
@@ -1472,6 +1473,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
* Returns true if we have permission to control remote app transisions
*/
public boolean hasControlRemoteAppTransitionPermission() {
+ if (!LawnchairApp.isRecentsEnabled()) return false;
return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
== PackageManager.PERMISSION_GRANTED;
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ec4edc2f9b..761c1539c6 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -126,6 +126,8 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.function.Function;
+import app.lawnchair.LawnchairApp;
+
/**
* Service connected by system-UI for handling touch interaction.
*/
@@ -151,7 +153,7 @@ public class TouchInteractionService extends Service
private int mBackGestureNotificationCounter = -1;
- private final TISBinder mTISBinder = new TISBinder();
+ private final TISBinder mTISBinder = LawnchairApp.isRecentsEnabled() ? new TISBinder() : null;
/**
* Local IOverviewProxy implementation with some methods for local components
@@ -362,6 +364,7 @@ public class TouchInteractionService extends Service
@Override
public void onCreate() {
super.onCreate();
+ if (!LawnchairApp.isRecentsEnabled()) return;
// Initialize anything here that is needed in direct boot mode.
// Everything else should be initialized in onUserUnlocked() below.
mMainChoreographer = Choreographer.getInstance();
@@ -540,6 +543,10 @@ public class TouchInteractionService extends Service
@Override
public void onDestroy() {
+ if (!LawnchairApp.isRecentsEnabled()) {
+ super.onDestroy();
+ return;
+ }
Log.d(TAG, "Touch service destroyed: user=" + getUserId());
sIsInitialized = false;
if (mDeviceState.isUserUnlocked()) {