Skip to content

Commit b1fc75a

Browse files
committed
#1798 feat: do not autostart PRO mode if device was not shutdown gracefully
1 parent 41177b6 commit b1fc75a

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

base/src/main/java/io/github/sds100/keymapper/base/BaseKeyMapperApp.kt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.github.sds100.keymapper.base
22

33
import android.annotation.SuppressLint
4+
import android.content.BroadcastReceiver
5+
import android.content.Context
46
import android.content.Intent
7+
import android.content.IntentFilter
58
import android.os.Build
69
import android.os.UserManager
710
import android.util.Log
@@ -35,6 +38,7 @@ import io.github.sds100.keymapper.system.permissions.Permission
3538
import io.github.sds100.keymapper.system.root.SuAdapterImpl
3639
import kotlinx.coroutines.CoroutineScope
3740
import kotlinx.coroutines.flow.collectLatest
41+
import kotlinx.coroutines.flow.first
3842
import kotlinx.coroutines.flow.launchIn
3943
import kotlinx.coroutines.flow.map
4044
import kotlinx.coroutines.flow.onEach
@@ -100,6 +104,25 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
100104
private val initLock: Any = Any()
101105
private var initialized = false
102106

107+
private val broadcastReceiver = object : BroadcastReceiver() {
108+
override fun onReceive(context: Context?, intent: Intent?) {
109+
context ?: return
110+
intent ?: return
111+
112+
when (intent.action) {
113+
Intent.ACTION_SHUTDOWN -> {
114+
Timber.i("Clean shutdown")
115+
settingsRepository.set(Keys.isCleanShutdown, true)
116+
117+
// Block until the value is persisted.
118+
runBlocking {
119+
settingsRepository.get(Keys.isCleanShutdown).first { it == true }
120+
}
121+
}
122+
}
123+
}
124+
}
125+
103126
override fun onCreate() {
104127
val priorExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
105128

@@ -123,7 +146,7 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
123146

124147
super.onCreate()
125148

126-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && userManager?.isUserUnlocked == false) {
149+
if (userManager?.isUserUnlocked == false) {
127150
Log.i(tag, "KeyMapperApp: Delay init because locked.")
128151
// If the device is still encrypted and locked do not initialize anything that
129152
// may potentially need the encrypted app storage like databases.
@@ -137,6 +160,8 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
137160
}
138161

139162
fun onBootUnlocked() {
163+
Log.i(tag, "KeyMapperApp: onBootUnlocked")
164+
140165
synchronized(initLock) {
141166
if (!initialized) {
142167
init()
@@ -148,6 +173,12 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
148173
private fun init() {
149174
Log.i(tag, "KeyMapperApp: Init")
150175

176+
val intentFilter = IntentFilter().apply {
177+
addAction(Intent.ACTION_SHUTDOWN)
178+
}
179+
180+
registerReceiver(broadcastReceiver, intentFilter)
181+
151182
settingsRepository.get(Keys.darkTheme)
152183
.map { it?.toIntOrNull() }
153184
.map {

base/src/main/java/io/github/sds100/keymapper/base/promode/SystemBridgeAutoStarter.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,18 @@ class SystemBridgeAutoStarter @Inject constructor(
126126
fun init() {
127127
coroutineScope.launch {
128128
// The Key Mapper process may not necessarily be started on boot due to the
129-
// on boot receiver so assume if it is started within 30 seconds of boot that
129+
// on boot receiver so assume if it is started within a minute of boot that
130130
// it should be auto started.
131-
val isBoot = SystemClock.uptimeMillis() < 30000
131+
val isBoot = SystemClock.uptimeMillis() < 60000
132+
133+
// Do not autostart if the device was force rebooted. This may be a sign that PRO mode
134+
// was broken and the user was trying to reset it.
135+
val isCleanShutdown = preferences.get(Keys.isCleanShutdown).map { it ?: false }.first()
136+
137+
Timber.i("SystemBridgeAutoStarter init: isBoot=$isBoot, isCleanShutdown=$isCleanShutdown")
138+
139+
// Reset the value after reading it.
140+
preferences.set(Keys.isCleanShutdown, false)
132141

133142
val isBootAutoStartEnabled = preferences.get(Keys.isProModeAutoStartBootEnabled)
134143
.map { it ?: PreferenceDefaults.PRO_MODE_AUTOSTART_BOOT }
@@ -140,7 +149,7 @@ class SystemBridgeAutoStarter @Inject constructor(
140149

141150
val connectionState = connectionManager.connectionState.value
142151

143-
if (isBoot && isBootAutoStartEnabled && connectionState !is SystemBridgeConnectionState.Connected) {
152+
if (isBoot && isCleanShutdown && isBootAutoStartEnabled && connectionState !is SystemBridgeConnectionState.Connected) {
144153
val autoStartType = autoStartTypeFlow.first()
145154

146155
if (autoStartType != null) {

base/src/main/java/io/github/sds100/keymapper/base/promode/SystemBridgeSetupAssistantController.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ class SystemBridgeSetupAssistantController @AssistedInject constructor(
364364
private fun getKeyMapperAppTask(): ActivityManager.AppTask? {
365365
val task = activityManager.appTasks
366366
.firstOrNull { it.taskInfo.topActivity?.className == keyMapperClassProvider.getMainActivity().name }
367+
367368
return task
368369
}
369370
}

data/src/main/java/io/github/sds100/keymapper/data/Keys.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,6 @@ object Keys {
125125
* Whether the user has started the system bridge before.
126126
*/
127127
val isSystemBridgeUsed = booleanPreferencesKey("key_is_system_bridge_used")
128+
129+
val isCleanShutdown = booleanPreferencesKey("key_is_clean_shutdown")
128130
}

0 commit comments

Comments
 (0)