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