Skip to content

Commit e6b6a5a

Browse files
committed
Merge branch 'feature/1905-system-bridge-logging' into develop
2 parents 5f0f0bf + ca2555f commit e6b6a5a

File tree

12 files changed

+426
-101
lines changed

12 files changed

+426
-101
lines changed

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

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import androidx.lifecycle.OnLifecycleEvent
1717
import androidx.lifecycle.ProcessLifecycleOwner
1818
import androidx.multidex.MultiDexApplication
1919
import io.github.sds100.keymapper.base.logging.KeyMapperLoggingTree
20+
import io.github.sds100.keymapper.base.logging.SystemBridgeLogger
2021
import io.github.sds100.keymapper.base.promode.SystemBridgeAutoStarter
2122
import io.github.sds100.keymapper.base.settings.Theme
2223
import io.github.sds100.keymapper.base.system.accessibility.AccessibilityServiceAdapterImpl
@@ -90,6 +91,9 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
9091
@Inject
9192
lateinit var systemBridgeConnectionManager: SystemBridgeConnectionManagerImpl
9293

94+
@Inject
95+
lateinit var systemBridgeLogger: SystemBridgeLogger
96+
9397
private val processLifecycleOwner by lazy { ProcessLifecycleOwner.get() }
9498

9599
private val userManager: UserManager? by lazy { getSystemService<UserManager>() }
@@ -186,20 +190,22 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
186190

187191
notificationController.init()
188192

189-
processLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
190-
@Suppress("DEPRECATION")
191-
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
192-
fun onResume() {
193-
// when the user returns to the app let everything know that the permissions could have changed
194-
notificationController.onOpenApp()
195-
196-
if (BuildConfig.DEBUG &&
197-
permissionAdapter.isGranted(Permission.WRITE_SECURE_SETTINGS)
198-
) {
199-
accessibilityServiceAdapter.start()
193+
processLifecycleOwner.lifecycle.addObserver(
194+
object : LifecycleObserver {
195+
@Suppress("DEPRECATION")
196+
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
197+
fun onResume() {
198+
// when the user returns to the app let everything know that the permissions could have changed
199+
notificationController.onOpenApp()
200+
201+
if (BuildConfig.DEBUG &&
202+
permissionAdapter.isGranted(Permission.WRITE_SECURE_SETTINGS)
203+
) {
204+
accessibilityServiceAdapter.start()
205+
}
200206
}
201-
}
202-
})
207+
},
208+
)
203209

204210
appCoroutineScope.launch {
205211
notificationController.openApp.collectLatest { intentAction ->
@@ -228,6 +234,11 @@ abstract class BaseKeyMapperApp : MultiDexApplication() {
228234
if (Build.VERSION.SDK_INT >= Constants.SYSTEM_BRIDGE_MIN_API) {
229235
systemBridgeAutoStarter.init()
230236

237+
// Initialize SystemBridgeLogger to start receiving log messages from SystemBridge.
238+
// Using Lazy<> to avoid circular dependency issues and ensure it's only created
239+
// when the API level requirement is met.
240+
systemBridgeLogger.start()
241+
231242
appCoroutineScope.launch {
232243
systemBridgeConnectionManager.connectionState.collect { state ->
233244
if (state is SystemBridgeConnectionState.Connected) {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package io.github.sds100.keymapper.base.logging
2+
3+
import android.util.Log
4+
import androidx.annotation.RequiresApi
5+
import io.github.sds100.keymapper.common.utils.Constants
6+
import io.github.sds100.keymapper.data.Keys
7+
import io.github.sds100.keymapper.data.repositories.PreferenceRepository
8+
import io.github.sds100.keymapper.sysbridge.ILogCallback
9+
import io.github.sds100.keymapper.sysbridge.manager.SystemBridgeConnectionManager
10+
import io.github.sds100.keymapper.sysbridge.manager.SystemBridgeConnectionState
11+
import javax.inject.Inject
12+
import javax.inject.Singleton
13+
import kotlinx.coroutines.CoroutineScope
14+
import kotlinx.coroutines.flow.SharingStarted
15+
import kotlinx.coroutines.flow.StateFlow
16+
import kotlinx.coroutines.flow.filterIsInstance
17+
import kotlinx.coroutines.flow.map
18+
import kotlinx.coroutines.flow.stateIn
19+
import kotlinx.coroutines.launch
20+
import timber.log.Timber
21+
22+
/**
23+
* Listens for SystemBridge connection and registers a log callback to receive
24+
* log messages from the Rust SystemBridge code. Respects the "extra logging"
25+
* preference to control the log level.
26+
*/
27+
@Singleton
28+
@RequiresApi(Constants.SYSTEM_BRIDGE_MIN_API)
29+
class SystemBridgeLogger @Inject constructor(
30+
private val coroutineScope: CoroutineScope,
31+
private val systemBridgeConnManager: SystemBridgeConnectionManager,
32+
private val preferenceRepository: PreferenceRepository,
33+
) : ILogCallback.Stub() {
34+
35+
private val extraLoggingEnabled: StateFlow<Boolean> =
36+
preferenceRepository.get(Keys.log)
37+
.map { it ?: false }
38+
.stateIn(coroutineScope, SharingStarted.Eagerly, false)
39+
40+
fun start() {
41+
// Listen for connection state changes
42+
coroutineScope.launch {
43+
systemBridgeConnManager.connectionState
44+
.filterIsInstance<SystemBridgeConnectionState.Connected>()
45+
.collect {
46+
registerWithSystemBridge()
47+
}
48+
}
49+
50+
// Listen for preference changes and update log level
51+
coroutineScope.launch {
52+
extraLoggingEnabled.collect { enabled ->
53+
updateLogLevel(enabled)
54+
}
55+
}
56+
}
57+
58+
private fun registerWithSystemBridge() {
59+
systemBridgeConnManager.run { bridge ->
60+
bridge.registerLogCallback(this@SystemBridgeLogger)
61+
bridge.setLogLevel(getSystemBridgeLogLevel(extraLoggingEnabled.value))
62+
}
63+
}
64+
65+
private fun updateLogLevel(extraLogging: Boolean) {
66+
systemBridgeConnManager.run { bridge ->
67+
bridge.setLogLevel(getSystemBridgeLogLevel(extraLogging))
68+
}
69+
}
70+
71+
override fun onLog(level: Int, message: String) {
72+
// Log with Timber so the messages appear under the Key Mapper package name
73+
// in logcat, and the KeyMapperLoggingTree will then save it to the LogRepository.
74+
Timber.log(priority = level, message = "systembridge: $message")
75+
}
76+
77+
private fun getSystemBridgeLogLevel(extraLogging: Boolean): Int {
78+
val level = if (extraLogging) {
79+
Log.DEBUG
80+
} else {
81+
Log.INFO
82+
}
83+
return level
84+
}
85+
}

evdev/src/main/rust/evdev_manager/Cargo.lock

Lines changed: 6 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

evdev/src/main/rust/evdev_manager/core/src/event_loop.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use evdev::enums::{EventType, EV_SYN};
1111
use evdev::util::event_code_to_int;
1212
use evdev::{InputEvent, ReadFlag, ReadStatus};
1313
use libc::c_uint;
14+
use log::Level;
1415
use mio::event::Event;
1516
use mio::{Events, Poll, Token, Waker};
1617
use std::error::Error;
@@ -216,10 +217,12 @@ impl EventLoopManager {
216217
code: u32,
217218
value: i32,
218219
) -> Result<(), EvdevError> {
219-
debug!(
220-
"Write evdev event: device_id={} event_type={} code={} value={}",
221-
device_id, event_type, code, value
222-
);
220+
if log_enabled!(Level::Debug) {
221+
debug!(
222+
"Write evdev event: device_id={} event_type={} code={} value={}",
223+
device_id, event_type, code, value
224+
);
225+
}
223226

224227
self.grab_controller
225228
.with_grabbed_device(device_id, |device| {
@@ -250,10 +253,12 @@ impl EventLoopManager {
250253
Err(Box::new(EvdevError::new(-libc::ENODATA)) as Box<dyn Error>)
251254
}
252255
Ok(Some(code)) => {
253-
debug!(
254-
"Write key code evdev event: key_code={} value={}",
255-
key_code, value
256-
);
256+
if log_enabled!(Level::Debug) {
257+
debug!(
258+
"Write key code evdev event: key_code={} value={}",
259+
key_code, value
260+
);
261+
}
257262

258263
device
259264
.uinput
@@ -365,8 +370,9 @@ impl EventLoopThread {
365370
match evdev.next_event(flags) {
366371
Ok((ReadStatus::Success, input_event)) => {
367372
flags = ReadFlag::NORMAL;
368-
// Keep this logging line. Debug/verbose events will be disabled in production.
369-
debug!("Evdev event: {:?}", input_event);
373+
if log_enabled!(Level::Debug) {
374+
debug!("Evdev event: {:?}", input_event);
375+
}
370376
self.process_event(slab_key, &input_event, device);
371377
}
372378
Ok((ReadStatus::Sync, _event)) => {

evdev/src/main/rust/evdev_manager/core/src/grabbed_device.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct GrabbedDevice {
2222
impl GrabbedDevice {
2323
/// Create a grabbed device that also enables the given EventCodes in the uinput device.
2424
pub fn new(device_path: &PathBuf, extra_events: &[EventCode]) -> Result<Self, EvdevError> {
25-
let mut evdev = Self::open_evdev_device(&device_path)?;
25+
let mut evdev = Self::open_evdev_device(device_path)?;
2626

2727
for event in extra_events {
2828
evdev.enable(*event)?;

evdev/src/main/rust/evdev_manager/jni/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ crate-type = ["rlib"]
1010
[dependencies]
1111
jni = "0.21.1"
1212
log = "0.4.28"
13-
android_log = "0.1.3"
1413
evdev = { path = "../../evdev" }
1514
evdev_manager_core = { path = "../core" }
1615
libc = "0.2.177"

0 commit comments

Comments
 (0)