diff --git a/peripheralmanager/AndroidManifest.xml b/peripheralmanager/AndroidManifest.xml
index 6d7de1b..c2d1088 100644
--- a/peripheralmanager/AndroidManifest.xml
+++ b/peripheralmanager/AndroidManifest.xml
@@ -43,5 +43,18 @@
android:resource="@string/stylus_summary" />
+
+
+
+
+
+
+
+
diff --git a/peripheralmanager/res/values/strings.xml b/peripheralmanager/res/values/strings.xml
index eb26843..c189cd6 100644
--- a/peripheralmanager/res/values/strings.xml
+++ b/peripheralmanager/res/values/strings.xml
@@ -14,4 +14,10 @@
Force recognize stylus
Enable this settings to allow using third party styluses
+
+ Keyboard
+ Keyboard Settings
+ Toggle angle detection
+ This toggles the angle detection of the keyboard
+
diff --git a/peripheralmanager/res/xml/keyboard_settings.xml b/peripheralmanager/res/xml/keyboard_settings.xml
new file mode 100644
index 0000000..06d6317
--- /dev/null
+++ b/peripheralmanager/res/xml/keyboard_settings.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/peripheralmanager/src/org/lineageos/xiaomiperipheralmanager/KeyboardSettingsActivity.java b/peripheralmanager/src/org/lineageos/xiaomiperipheralmanager/KeyboardSettingsActivity.java
new file mode 100644
index 0000000..049ec68
--- /dev/null
+++ b/peripheralmanager/src/org/lineageos/xiaomiperipheralmanager/KeyboardSettingsActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023-2025 The LineageOS Project
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.xiaomiperipheralmanager;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
+
+/**
+ * Settings activity for stylus/pen configuration
+ * Hosts the StylusSettingsFragment for user configuration
+ */
+public class KeyboardSettingsActivity extends CollapsingToolbarBaseActivity {
+
+ private static final String TAG = "XiaomiKeyboardSettings";
+ private static final String TAG_KEYBOARD = "keyboard";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Log.i(TAG, "Opening keyboard settings");
+
+ getFragmentManager().beginTransaction().replace(
+ com.android.settingslib.collapsingtoolbar.R.id.content_frame,
+ new KeyboardSettingsFragment(), TAG_KEYBOARD).commit();
+ }
+}
diff --git a/peripheralmanager/src/org/lineageos/xiaomiperipheralmanager/KeyboardSettingsFragment.java b/peripheralmanager/src/org/lineageos/xiaomiperipheralmanager/KeyboardSettingsFragment.java
new file mode 100644
index 0000000..a7e256a
--- /dev/null
+++ b/peripheralmanager/src/org/lineageos/xiaomiperipheralmanager/KeyboardSettingsFragment.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023-2025 The LineageOS Project
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.xiaomiperipheralmanager;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+
+import android.preference.PreferenceManager;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.SwitchPreference;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class KeyboardSettingsFragment extends PreferenceFragment implements
+ SharedPreferences.OnSharedPreferenceChangeListener {
+
+ private static final String TAG = "XiaomiKeyboardSettings";
+ private static final String KEYBOARD_KEY = "keyboard_switch_key";
+ private static final boolean DEBUG = true;
+ private static final String CONF_LOCATION = "/data/misc/xiaomi_keyboard.conf";
+
+ private SharedPreferences mKeyboardPreference;
+
+ private void saveAngleDetectionPreference(boolean enabled) {
+ try {
+ File file = new File(CONF_LOCATION);
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write((enabled ? "1" : "0").getBytes());
+ fos.close();
+ logInfo("Angle detection preference saved: " + enabled);
+ } catch (IOException e) {
+ logError("Failed to save angle detection preference: " + e.getMessage());
+ }
+}
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ try {
+ addPreferencesFromResource(R.xml.keyboard_settings);
+
+ mKeyboardPreference = PreferenceManager.getDefaultSharedPreferences(getContext());
+ SwitchPreference switchPreference = (SwitchPreference) findPreference(KEYBOARD_KEY);
+
+ if (switchPreference != null) {
+ switchPreference.setChecked(mKeyboardPreference.getBoolean(KEYBOARD_KEY, false));
+ switchPreference.setEnabled(true);
+ } else {
+ logError("Could not find keyboard switch preference");
+ }
+
+ logInfo("Keyboard settings fragment created");
+ } catch (Exception e) {
+ logError("Error creating keyboard settings: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ try {
+ mKeyboardPreference.registerOnSharedPreferenceChangeListener(this);
+ logDebug("Registered preference change listener");
+
+ } catch (Exception e) {
+ logError("Error in onResume: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ try {
+ mKeyboardPreference.unregisterOnSharedPreferenceChangeListener(this);
+ logDebug("Unregistered preference change listener");
+
+ } catch (Exception e) {
+ logError("Error in onPause: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreference, String key) {
+ if (KEYBOARD_KEY.equals(key)) {
+ try {
+ boolean newStatus = mKeyboardPreference.getBoolean(key, false);
+ saveAngleDetectionPreference(newStatus);
+ logInfo("Keyboard status changed: " + newStatus);
+ } catch (Exception e) {
+ logError("Error handling preference change: " + e.getMessage());
+ }
+ }
+ }
+
+ // Enhanced logging helpers to match other classes
+ private void logDebug(String message) {
+ if (DEBUG) Log.d(TAG, getTimestamp() + message);
+ }
+
+ private void logInfo(String message) {
+ Log.i(TAG, getTimestamp() + message);
+ }
+
+ private void logError(String message) {
+ Log.e(TAG, getTimestamp() + message);
+ }
+
+ private String getTimestamp() {
+ return "[" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(new Date()) + "] ";
+ }
+}
\ No newline at end of file
diff --git a/peripheralmanager/xiaomi-keyboard.cpp b/peripheralmanager/xiaomi-keyboard.cpp
index 572dc91..b6fe01d 100644
--- a/peripheralmanager/xiaomi-keyboard.cpp
+++ b/peripheralmanager/xiaomi-keyboard.cpp
@@ -93,16 +93,42 @@ bool kb_thread_paused = false;
// Condition variable for the sensor thread
pthread_mutex_t sensor_mutex = PTHREAD_MUTEX_INITIALIZER;
+// For the preference thread
+pthread_mutex_t angle_detection_mutex = PTHREAD_MUTEX_INITIALIZER;
+
// Add these global variables
time_t last_monitor_activity = time(NULL);
pthread_t watchdog_thread;
bool watchdog_enabled = true;
-// Add a default config that can be used instead of parsing a file
-const bool DEFAULT_WATCHDOG_ENABLED = true;
+// Angle detection enable flag
+bool angle_detection_enabled = false; // Default value
-// Constants
-#define POLL_INTERVAL_MS 500 // How often to poll
+void load_angle_detection_preference() {
+ FILE* f = fopen("/data/misc/xiaomi_keyboard.conf", "r");
+ if (f) {
+ int c = fgetc(f);
+ pthread_mutex_lock(&angle_detection_mutex);
+ angle_detection_enabled = (c == '1');
+ pthread_mutex_lock(&angle_detection_mutex);
+ fclose(f);
+ LOGI("Angle detection preference loaded: %s",
+ angle_detection_enabled ? "enabled" : "disabled");
+ } else {
+ LOGW(
+ "Could not open /data/misc/xiaomi_keyboard.conf, using default "
+ "(enabled)");
+ // angle_detection_enabled = true;
+ }
+}
+
+void* preference_watcher_thread(void*) {
+ while (!terminate) {
+ load_angle_detection_preference();
+ sleep(10); // Reload every 10 seconds
+ }
+ return NULL;
+}
// Globals
static ASensorManager* sensorManager = NULL;
@@ -135,7 +161,7 @@ void* accelerometer_thread(void* args) {
ASensor_getMinDelay(accelerometer));
while (!terminate) {
- ALooper_pollOnce(POLL_INTERVAL_MS, NULL, NULL, NULL);
+ ALooper_pollOnce(500, NULL, NULL, NULL);
if (terminate) break;
ASensorEvent event;
@@ -572,6 +598,10 @@ void handle_accel_event(char* buffer) {
* Main event handler - dispatches to appropriate handler based on message type
*/
void handle_event(char* buffer, ssize_t bytes_read) {
+ pthread_mutex_lock(&angle_detection_mutex);
+ bool angle_detection_enabled_local = angle_detection_enabled;
+ pthread_mutex_unlock(&angle_detection_mutex);
+
// Basic validation
if (bytes_read < 7 || buffer[1] != MSG_HEADER_1 ||
buffer[2] != MSG_HEADER_2) {
@@ -585,7 +615,8 @@ void handle_event(char* buffer, ssize_t bytes_read) {
}
} else if (buffer[4] == MSG_TYPE_LOCK || buffer[4] == MSG_TYPE_UNLOCK) {
handle_lock_event(buffer);
- } else if (buffer[4] == MSG_TYPE_MOVEMENT) {
+ } else if (buffer[4] == MSG_TYPE_MOVEMENT && angle_detection_enabled_local) {
+ LOGI("angle_detection_enabled: %d", angle_detection_enabled_local);
handle_accel_event(buffer);
}
}
@@ -685,6 +716,9 @@ int main() {
LOGI("Xiaomi keyboard service v%s starting at %s", VERSION_STRING, time_str);
+ // Load angle detection preference
+ load_angle_detection_preference();
+
ssize_t bytes_read;
char buffer[BUFFER_SIZE];
@@ -765,6 +799,11 @@ int main() {
pthread_create(&sensor_thread, NULL, accelerometer_thread, NULL);
pthread_detach(sensor_thread);
+ // Create the preference watching thread
+ pthread_t preference_thread;
+ pthread_create(&preference_thread, NULL, preference_watcher_thread, NULL);
+ pthread_detach(preference_thread);
+
// Set up signal handling
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
diff --git a/rootdir/etc/init.device.rc b/rootdir/etc/init.device.rc
index b30f0ed..c27e96d 100644
--- a/rootdir/etc/init.device.rc
+++ b/rootdir/etc/init.device.rc
@@ -30,3 +30,7 @@ service xiaomi-keyboard /vendor/bin/xiaomi-keyboard
on property:persist.vendor.parts.pen=*
start xiaomi-pen
+
+on post-data-fs
+ exec - system system -- /system/bin/touch /data/misc/xiaomi_keyboard.conf
+ exec - system system -- /system/bin/restorecon /data/misc/xiaomi_keyboard.conf