@@ -69,54 +69,61 @@ class SystemBridgeAutoStarter @Inject constructor(
6969 private val notificationAdapter : NotificationAdapter ,
7070 private val resourceProvider : ResourceProvider ,
7171) : ResourceProvider by resourceProvider {
72- enum class AutoStartType {
72+
73+ private enum class AutoStartType {
7374 ADB ,
7475 SHIZUKU ,
7576 ROOT ,
7677 }
7778
79+ private sealed class AutoStartEligibility {
80+ data class Eligible (val type : AutoStartType ) : AutoStartEligibility()
81+ sealed class NotEligible : AutoStartEligibility () {
82+ data object WiFiDisconnected : NotEligible ()
83+ data object AutoStartCooldown : NotEligible ()
84+ data object Other : NotEligible ()
85+ }
86+ }
87+
7888 // Use flatMapLatest so that any calls to ADB are only done if strictly necessary.
7989 @SuppressLint(" NewApi" )
8090 @OptIn(ExperimentalCoroutinesApi ::class )
81- private val autoStartTypeFlow: Flow <AutoStartType ? > =
91+ private val autoStartTypeFlow: Flow <AutoStartEligibility > =
8292 suAdapter.isRootGranted
8393 .filterNotNull()
8494 .flatMapLatest { isRooted ->
8595 if (isRooted) {
86- flowOf(AutoStartType .ROOT )
87- } else {
88- val useShizukuFlow =
89- combine(
90- shizukuAdapter.isStarted,
91- permissionAdapter.isGrantedFlow(Permission .SHIZUKU ),
92- ) { isStarted, isGranted ->
93- isStarted && isGranted
94- }
96+ return @flatMapLatest flowOf(AutoStartEligibility .Eligible (AutoStartType .ROOT ))
97+ }
9598
96- useShizukuFlow.flatMapLatest { useShizuku ->
97- if (useShizuku) {
98- flowOf(AutoStartType .SHIZUKU )
99- } else if (buildConfig.sdkInt >= Build .VERSION_CODES .R ) {
100- val isAdbAutoStartAllowed = combine(
101- permissionAdapter.isGrantedFlow(Permission .WRITE_SECURE_SETTINGS ),
102- networkAdapter.isWifiConnected,
103- ) { isWriteSecureSettingsGranted, isWifiConnected ->
104- isWriteSecureSettingsGranted &&
105- isWifiConnected &&
106- setupController.isAdbPaired()
107- }
99+ val useShizukuFlow =
100+ combine(
101+ shizukuAdapter.isStarted,
102+ permissionAdapter.isGrantedFlow(Permission .SHIZUKU ),
103+ ) { isStarted, isGranted ->
104+ isStarted && isGranted
105+ }
108106
109- isAdbAutoStartAllowed.distinctUntilChanged()
110- .map { isAdbAutoStartAllowed ->
111- if (isAdbAutoStartAllowed) {
112- AutoStartType .ADB
113- } else {
114- null
115- }
116- }.filterNotNull()
117- } else {
118- flowOf(null )
107+ useShizukuFlow.flatMapLatest { useShizuku ->
108+ if (useShizuku) {
109+ flowOf(AutoStartEligibility .Eligible (AutoStartType .SHIZUKU ))
110+ } else if (buildConfig.sdkInt >= Build .VERSION_CODES .R ) {
111+ combine(
112+ permissionAdapter.isGrantedFlow(Permission .WRITE_SECURE_SETTINGS ),
113+ networkAdapter.isWifiConnected,
114+ ) { isWriteSecureSettingsGranted, isWifiConnected ->
115+ if (! isWifiConnected) {
116+ AutoStartEligibility .NotEligible .WiFiDisconnected
117+ } else if (! isWriteSecureSettingsGranted) {
118+ AutoStartEligibility .NotEligible .Other
119+ } else if (! setupController.isAdbPaired()) {
120+ AutoStartEligibility .NotEligible .Other
121+ } else {
122+ AutoStartEligibility .Eligible (AutoStartType .ADB )
123+ }
119124 }
125+ } else {
126+ flowOf(AutoStartEligibility .NotEligible .Other )
120127 }
121128 }
122129 }
@@ -125,7 +132,7 @@ class SystemBridgeAutoStarter @Inject constructor(
125132 * This emits values when the system bridge needs restarting after it being killed.
126133 */
127134 @OptIn(ExperimentalCoroutinesApi ::class )
128- private val autoStartFlow: Flow <AutoStartType ? > =
135+ private val autoStartFlow: Flow <AutoStartEligibility > =
129136 connectionManager.connectionState.flatMapLatest { connectionState ->
130137 // Do not autostart if it is connected or it was killed from the user
131138 if (connectionState !is SystemBridgeConnectionState .Disconnected ||
@@ -135,17 +142,9 @@ class SystemBridgeAutoStarter @Inject constructor(
135142 isSystemBridgeEmergencyKilled() ||
136143 ! isAutoStartEnabled()
137144 ) {
138- flowOf(null )
145+ flowOf(AutoStartEligibility . NotEligible . Other )
139146 } else if (isWithinAutoStartCooldown()) {
140- // Do not autostart if the system bridge was killed shortly after.
141- // This prevents infinite loops happening.
142- Timber .w(
143- " Not auto starting the system bridge because it was last auto started less than 5 mins ago" ,
144- )
145- showSystemBridgeKilledNotification(
146- getString(R .string.system_bridge_died_notification_not_restarting_text),
147- )
148- flowOf(null )
147+ flowOf(AutoStartEligibility .NotEligible .AutoStartCooldown )
149148 } else {
150149 autoStartTypeFlow
151150 }
@@ -178,10 +177,28 @@ class SystemBridgeAutoStarter @Inject constructor(
178177
179178 autoStartFlow
180179 .distinctUntilChanged() // Must come before the filterNotNull
181- .filterNotNull()
182- .collectLatest { type ->
183- autoStart(type)
184- }
180+ .collectLatest(::processAutoStartEligibility)
181+ }
182+ }
183+
184+ private suspend fun processAutoStartEligibility (eligibility : AutoStartEligibility ) {
185+ when (eligibility) {
186+ is AutoStartEligibility .Eligible -> autoStart(eligibility.type)
187+
188+ AutoStartEligibility .NotEligible .AutoStartCooldown -> {
189+ // Do not autostart if the system bridge was killed shortly after.
190+ // This prevents infinite loops happening.
191+ Timber .w(
192+ " Not auto starting the system bridge because it was last auto started less than 5 mins ago" ,
193+ )
194+ showSystemBridgeKilledNotification(
195+ getString(R .string.system_bridge_died_notification_not_restarting_text),
196+ )
197+ }
198+
199+ AutoStartEligibility .NotEligible .WiFiDisconnected -> showWiFiDisconnectedNotification()
200+
201+ AutoStartEligibility .NotEligible .Other -> {}
185202 }
186203 }
187204
@@ -353,7 +370,27 @@ class SystemBridgeAutoStarter @Inject constructor(
353370 priority = NotificationCompat .PRIORITY_MAX ,
354371 onGoing = true ,
355372 showIndeterminateProgress = true ,
356- showOnLockscreen = false ,
373+ showOnLockscreen = true ,
374+ )
375+
376+ notificationAdapter.showNotification(model)
377+ }
378+
379+ private fun showWiFiDisconnectedNotification () {
380+ val model = NotificationModel (
381+ id = ID_SYSTEM_BRIDGE_STATUS ,
382+ title = getString(
383+ R .string.system_bridge_wifi_disconnected_notification_title,
384+ ),
385+ text = getString(R .string.system_bridge_wifi_disconnected_notification_text),
386+ onClickAction = KMNotificationAction .Activity .MainActivity (
387+ BaseMainActivity .ACTION_START_SYSTEM_BRIDGE ,
388+ ),
389+ channel = CHANNEL_SETUP_ASSISTANT ,
390+ icon = R .drawable.offline_bolt_24px,
391+ priority = NotificationCompat .PRIORITY_MAX ,
392+ onGoing = false ,
393+ showOnLockscreen = true ,
357394 )
358395
359396 notificationAdapter.showNotification(model)
@@ -371,7 +408,7 @@ class SystemBridgeAutoStarter @Inject constructor(
371408 channel = CHANNEL_SETUP_ASSISTANT ,
372409 icon = R .drawable.offline_bolt_24px,
373410 onGoing = false ,
374- showOnLockscreen = false ,
411+ showOnLockscreen = true ,
375412 autoCancel = true ,
376413 priority = NotificationCompat .PRIORITY_MAX ,
377414 onClickAction = KMNotificationAction .Activity .MainActivity (
0 commit comments