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