feat(gestures): add user-selectable sleep method preference (#6664)
Allow users to choose their preferred sleep method (Auto/Root/ Accessibility Service/Device Admin) for the double-tap-to-sleep gesture, instead of relying on the fixed priority fallback chain. This addresses the issue where OEM ROMs aggressively kill accessibility services, making the sleep gesture unreliable on non-rooted devices. Users can now explicitly select Device Admin as an alternative that won't be killed by battery optimization. Closes #6463
This commit is contained in:
@@ -616,6 +616,12 @@
|
||||
<string name="generic_a11y_hint">To %1$s, turn on the Lawnchair accessibility service. Tap \"Open settings\", select \"Lawnchair\" and turn on \"Use Lawnchair.\"</string>
|
||||
<string name="generic_a11y_disclaimer">Lawnchair uses Accessibility\'s `performGlobalAction` method to perform this action. This is a sensitive permission that allows monitoring other apps. However, Lawnchair is not configured for that functionality and receives no events.</string>
|
||||
|
||||
<string name="sleep_mode_label">Sleep mode</string>
|
||||
<string name="sleep_mode_auto">Automatic</string>
|
||||
<string name="sleep_mode_root">Root</string>
|
||||
<string name="sleep_mode_accessibility">Accessibility service</string>
|
||||
<string name="sleep_mode_device_admin">Device admin</string>
|
||||
|
||||
<!--
|
||||
|
||||
Bug reporting
|
||||
|
||||
@@ -25,16 +25,31 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import app.lawnchair.LawnchairLauncher
|
||||
import app.lawnchair.preferences2.PreferenceManager2
|
||||
import app.lawnchair.util.requireSystemService
|
||||
import app.lawnchair.views.ComposeBottomSheet
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
||||
class SleepGestureHandler(context: Context) : GestureHandler(context) {
|
||||
|
||||
override suspend fun onTrigger(launcher: LawnchairLauncher) {
|
||||
methods.first { it.isSupported() }.sleep(launcher)
|
||||
val pref = PreferenceManager2.getInstance(context).sleepMode.get().first()
|
||||
val method = when (pref) {
|
||||
SleepMode.AUTO -> methods.first { it.isSupported() }
|
||||
SleepMode.ROOT -> methods.filterIsInstance<SleepMethodRoot>().first()
|
||||
SleepMode.ACCESSIBILITY -> methods.filterIsInstance<SleepMethodPieAccessibility>().first()
|
||||
SleepMode.DEVICE_ADMIN -> methods.filterIsInstance<SleepMethodDeviceAdmin>().first()
|
||||
}
|
||||
|
||||
if (pref != SleepMode.AUTO && !method.isSupported()) {
|
||||
methods.first { it.isSupported() }.sleep(launcher)
|
||||
return
|
||||
}
|
||||
|
||||
method.sleep(launcher)
|
||||
}
|
||||
|
||||
private val methods = listOf(
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package app.lawnchair.gestures.handlers
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
|
||||
import com.android.launcher3.R
|
||||
|
||||
enum class SleepMode(
|
||||
@StringRes val labelResourceId: Int,
|
||||
) {
|
||||
AUTO(
|
||||
labelResourceId = R.string.sleep_mode_auto,
|
||||
),
|
||||
ROOT(
|
||||
labelResourceId = R.string.sleep_mode_root,
|
||||
),
|
||||
ACCESSIBILITY(
|
||||
labelResourceId = R.string.sleep_mode_accessibility,
|
||||
),
|
||||
DEVICE_ADMIN(
|
||||
labelResourceId = R.string.sleep_mode_device_admin,
|
||||
),
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun values() = enumValues<SleepMode>().toList()
|
||||
|
||||
fun fromString(string: String) = values().firstOrNull { it.toString() == string }
|
||||
|
||||
fun entries(): List<ListPreferenceEntry<SleepMode>> = values().map {
|
||||
ListPreferenceEntry(value = it) { stringResource(id = it.labelResourceId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import androidx.datastore.preferences.preferencesDataStore
|
||||
import app.lawnchair.data.Converters
|
||||
import app.lawnchair.font.FontCache
|
||||
import app.lawnchair.gestures.config.GestureHandlerConfig
|
||||
import app.lawnchair.gestures.handlers.SleepMode
|
||||
import app.lawnchair.gestures.type.GestureType
|
||||
import app.lawnchair.hotseat.HotseatMode
|
||||
import app.lawnchair.icons.CustomAdaptiveIconDrawable
|
||||
@@ -747,6 +748,13 @@ class PreferenceManager2 @Inject constructor(
|
||||
defaultValue = GestureHandlerConfig.Sleep,
|
||||
)
|
||||
|
||||
val sleepMode = preference(
|
||||
key = stringPreferencesKey(name = "sleep_mode"),
|
||||
defaultValue = SleepMode.AUTO,
|
||||
parse = { SleepMode.fromString(it) ?: SleepMode.AUTO },
|
||||
save = { it.toString() },
|
||||
)
|
||||
|
||||
val swipeUpGestureHandler = serializablePreference<GestureHandlerConfig>(
|
||||
key = stringPreferencesKey("swipe_up_gesture_handler"),
|
||||
defaultValue = GestureHandlerConfig.OpenAppDrawer,
|
||||
|
||||
@@ -3,10 +3,12 @@ package app.lawnchair.ui.preferences.destinations
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.lawnchair.gestures.handlers.SleepMode
|
||||
import app.lawnchair.preferences.getAdapter
|
||||
import app.lawnchair.preferences2.preferenceManager2
|
||||
import app.lawnchair.ui.preferences.LocalIsExpandedScreen
|
||||
import app.lawnchair.ui.preferences.components.GestureHandlerPreference
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreference
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
|
||||
import com.android.launcher3.R
|
||||
@@ -65,5 +67,14 @@ fun GesturePreferences(
|
||||
)
|
||||
}
|
||||
}
|
||||
PreferenceGroup(heading = stringResource(id = R.string.sleep_mode_label)) {
|
||||
Item {
|
||||
ListPreference(
|
||||
adapter = prefs.sleepMode.getAdapter(),
|
||||
entries = SleepMode.entries(),
|
||||
label = stringResource(id = R.string.sleep_mode_label),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user