diff --git a/app/src/main/java/de/langerhans/odintools/main/MainViewModel.kt b/app/src/main/java/de/langerhans/odintools/main/MainViewModel.kt index dfd3fcb..fe7694a 100644 --- a/app/src/main/java/de/langerhans/odintools/main/MainViewModel.kt +++ b/app/src/main/java/de/langerhans/odintools/main/MainViewModel.kt @@ -36,8 +36,7 @@ class MainViewModel @Inject constructor( get() = _l2r2StyleOptions init { - executor.enableA11yService() - executor.grantAllAppsPermission() + executor.applyRequiredSettings() val deviceType = deviceUtils.getDeviceType() val preventHomePressSetting = executor.getBooleanSystemSetting("prevent_press_home_accidentally", true) @@ -178,7 +177,7 @@ class MainViewModel @Inject constructor( it.copy( showRemapButtonDialog = true, currentButtonSetting = setting, - currentButtonKeyCode = executor.getSystemSetting(setting, 0) + currentButtonKeyCode = executor.getIntSystemSetting(setting, 0) ) } } @@ -201,14 +200,14 @@ class MainViewModel @Inject constructor( fun resetButtonKeyCode(setting: String) { val newValue: Int = getDefaultKeyCode(setting) - executor.setSystemSetting(setting, newValue) + executor.setIntSystemSetting(setting, newValue) _uiState.update { it.copy(showRemapButtonDialog = false) } } fun saveButtonKeyCode(setting: String, newValue: Int) { - executor.setSystemSetting(setting, newValue) + executor.setIntSystemSetting(setting, newValue) _uiState.update { it.copy(showRemapButtonDialog = false) } diff --git a/app/src/main/java/de/langerhans/odintools/models/ControllerStyle.kt b/app/src/main/java/de/langerhans/odintools/models/ControllerStyle.kt index e231d18..4067abd 100644 --- a/app/src/main/java/de/langerhans/odintools/models/ControllerStyle.kt +++ b/app/src/main/java/de/langerhans/odintools/models/ControllerStyle.kt @@ -18,9 +18,9 @@ sealed class ControllerStyle( fun enable(executor: ShellExecutor) { if (this != Unknown) { - executor.setSystemSetting(TEMP_ABXY_LAYOUT_MODE, tempAbxyLayout) - executor.setSystemSetting(NO_CREATE_GAMEPAD_BUTTON_LAYOUT, noCreateGamepadLayout) - executor.setSystemSetting(FLIP_BUTTON_LAYOUT, flipButtonLayout) + executor.setIntSystemSetting(TEMP_ABXY_LAYOUT_MODE, tempAbxyLayout) + executor.setIntSystemSetting(NO_CREATE_GAMEPAD_BUTTON_LAYOUT, noCreateGamepadLayout) + executor.setIntSystemSetting(FLIP_BUTTON_LAYOUT, flipButtonLayout) } } @@ -30,8 +30,8 @@ sealed class ControllerStyle( private const val FLIP_BUTTON_LAYOUT = "flip_button_layout" fun getStyle(executor: ShellExecutor): ControllerStyle { - return if (executor.getSystemSetting(NO_CREATE_GAMEPAD_BUTTON_LAYOUT, 0) == 1) Disconnect - else if (executor.getSystemSetting(FLIP_BUTTON_LAYOUT, 0) == 1) Xbox + return if (executor.getIntSystemSetting(NO_CREATE_GAMEPAD_BUTTON_LAYOUT, 0) == 1) Disconnect + else if (executor.getIntSystemSetting(FLIP_BUTTON_LAYOUT, 0) == 1) Xbox else Odin } diff --git a/app/src/main/java/de/langerhans/odintools/models/FanMode.kt b/app/src/main/java/de/langerhans/odintools/models/FanMode.kt index 2806404..b63c6e1 100644 --- a/app/src/main/java/de/langerhans/odintools/models/FanMode.kt +++ b/app/src/main/java/de/langerhans/odintools/models/FanMode.kt @@ -17,7 +17,7 @@ sealed class FanMode( fun enable(executor: ShellExecutor) { if (this != Unknown) { - executor.setSystemSetting(FAN_MODE, settingsValue) + executor.setIntSystemSetting(FAN_MODE, settingsValue) } } @@ -25,7 +25,7 @@ sealed class FanMode( private const val FAN_MODE = "fan_mode" fun getMode(executor: ShellExecutor) = - when (executor.getSystemSetting(FAN_MODE, Quiet.settingsValue)) { + when (executor.getIntSystemSetting(FAN_MODE, Quiet.settingsValue)) { Quiet.settingsValue -> Quiet Smart.settingsValue -> Smart Sport.settingsValue -> Sport diff --git a/app/src/main/java/de/langerhans/odintools/models/L2R2Style.kt b/app/src/main/java/de/langerhans/odintools/models/L2R2Style.kt index a780f7d..e673b10 100644 --- a/app/src/main/java/de/langerhans/odintools/models/L2R2Style.kt +++ b/app/src/main/java/de/langerhans/odintools/models/L2R2Style.kt @@ -2,7 +2,6 @@ package de.langerhans.odintools.models import androidx.annotation.StringRes import de.langerhans.odintools.R -import de.langerhans.odintools.tiles.L2R2TileService import de.langerhans.odintools.tools.ShellExecutor sealed class L2R2Style( @@ -17,7 +16,7 @@ sealed class L2R2Style( fun enable(executor: ShellExecutor) { if (this != Unknown) { - executor.setSystemSetting(TRIGGER_INPUT_MODE, settingsValue) + executor.setIntSystemSetting(TRIGGER_INPUT_MODE, settingsValue) } } @@ -25,7 +24,7 @@ sealed class L2R2Style( private const val TRIGGER_INPUT_MODE = "trigger_input_mode" fun getStyle(executor: ShellExecutor) = - when (executor.getSystemSetting(TRIGGER_INPUT_MODE, Analog.settingsValue)) { + when (executor.getIntSystemSetting(TRIGGER_INPUT_MODE, Analog.settingsValue)) { Analog.settingsValue -> Analog Digital.settingsValue -> Digital Both.settingsValue -> Both diff --git a/app/src/main/java/de/langerhans/odintools/models/PerfMode.kt b/app/src/main/java/de/langerhans/odintools/models/PerfMode.kt index 7ee261a..4d15983 100644 --- a/app/src/main/java/de/langerhans/odintools/models/PerfMode.kt +++ b/app/src/main/java/de/langerhans/odintools/models/PerfMode.kt @@ -16,7 +16,7 @@ sealed class PerfMode( fun enable(executor: ShellExecutor) { if (this != Unknown) { - executor.setSystemSetting(PERFORMANCE_MODE, settingsValue) + executor.setIntSystemSetting(PERFORMANCE_MODE, settingsValue) } } @@ -24,7 +24,7 @@ sealed class PerfMode( private const val PERFORMANCE_MODE = "performance_mode" fun getMode(executor: ShellExecutor) = - when (executor.getSystemSetting(PERFORMANCE_MODE, Standard.settingsValue)) { + when (executor.getIntSystemSetting(PERFORMANCE_MODE, Standard.settingsValue)) { Standard.settingsValue -> Standard Performance.settingsValue -> Performance HighPerformance.settingsValue -> HighPerformance diff --git a/app/src/main/java/de/langerhans/odintools/tools/ShellExecutor.kt b/app/src/main/java/de/langerhans/odintools/tools/ShellExecutor.kt index 761baa7..f3d9cc3 100644 --- a/app/src/main/java/de/langerhans/odintools/tools/ShellExecutor.kt +++ b/app/src/main/java/de/langerhans/odintools/tools/ShellExecutor.kt @@ -3,6 +3,7 @@ package de.langerhans.odintools.tools import android.annotation.SuppressLint import android.os.IBinder import android.os.Parcel +import de.langerhans.odintools.BuildConfig import java.nio.charset.Charset import javax.inject.Inject @@ -33,41 +34,51 @@ class ShellExecutor @Inject constructor() { .getOrElse { return Result.failure(it) } - val result = reply.createByteArray()?.toString(Charset.defaultCharset())?.trim() + val result = reply.createByteArray()?.toString(Charset.defaultCharset())?.trim()?.let { + if (it == "null") null else it + } data.recycle() reply.recycle() return Result.success(result) } - fun getSystemSetting(setting: String, defaultValue: Int): Int { + fun getIntSystemSetting(setting: String, defaultValue: Int): Int { return executeAsRoot("settings get system $setting") - .map { if (it == null || it == "null") defaultValue else it.toInt() } + .mapCatching { it?.toInt() ?: defaultValue } .getOrDefault(defaultValue) } - fun setSystemSetting(setting: String, value: Int) { + fun setIntSystemSetting(setting: String, value: Int) { executeAsRoot("settings put system $setting $value") } - fun setBooleanSystemSetting(setting: String, value: Boolean) { - setSystemSetting(setting, if (value) 1 else 0) - } - fun getBooleanSystemSetting(setting: String, defaultValue: Boolean): Boolean { return executeAsRoot("settings get system $setting") .map { if (it == null) defaultValue else it == "1" } .getOrDefault(defaultValue) } - fun enableA11yService() { + fun setBooleanSystemSetting(setting: String, value: Boolean) { + setIntSystemSetting(setting, if (value) 1 else 0) + } + + fun getStringSystemSetting(setting: String, defaultValue: String): String { + return executeAsRoot("settings get system $setting").map { + it ?: defaultValue + }.getOrDefault(defaultValue) + } + + fun setStringSystemSetting(setting: String, value: String) { + executeAsRoot("settings put system $setting $value") + } + + private fun enableA11yService() { val currentServices = executeAsRoot("settings get secure enabled_accessibility_services") - .map { - if (it == null || it == "null") "" else it - } + .map { it ?: "" } .getOrDefault("") - if (currentServices.contains("de.langerhans.odintools")) return + if (currentServices.contains(PACKAGE)) return executeAsRoot( "settings put secure enabled_accessibility_services $PACKAGE/$PACKAGE.service.ForegroundAppWatcherService:$currentServices" @@ -91,11 +102,28 @@ class ShellExecutor @Inject constructor() { .getOrDefault(defaultValue) } - fun grantAllAppsPermission() { + private fun grantAllAppsPermission() { executeAsRoot("pm grant $PACKAGE android.permission.QUERY_ALL_PACKAGES") } + private fun addOdinToolsToWhitelist() { + val currentWhitelist = getStringSystemSetting("app_whiteList", "") + if (currentWhitelist.contains(PACKAGE)) return + + val newWhitelist = "$PACKAGE,$currentWhitelist".trimEnd(',') + setStringSystemSetting("app_whiteList", newWhitelist) + } + + fun applyRequiredSettings() { + enableA11yService() + grantAllAppsPermission() + if (!BuildConfig.DEBUG) { + // Don't add to whitelist on debug builds, otherwise even Android Studio can't kill the app + addOdinToolsToWhitelist() + } + } + companion object { - private const val PACKAGE = "de.langerhans.odintools" + private const val PACKAGE = BuildConfig.APPLICATION_ID } }