pipa: peripheralmanager: Implement a toggle for kb angle detection
This commit is contained in:
@@ -43,5 +43,18 @@
|
||||
android:resource="@string/stylus_summary" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".KeyboardSettingsActivity"
|
||||
android:label="@string/keyboard_title"
|
||||
android:theme="@style/Theme.SubSettingsBase">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.settings.action.IA_SETTINGS" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.connect" />
|
||||
<meta-data android:name="com.android.settings.summary"
|
||||
android:resource="@string/keyboard_summary" />
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -14,4 +14,10 @@
|
||||
<string name="stylus_switch_title">Force recognize stylus</string>
|
||||
<string name="stylus_switch_summary">Enable this settings to allow using third party styluses</string>
|
||||
|
||||
<!-- Xiaomi Stylus -->
|
||||
<string name="keyboard_title">Keyboard</string>
|
||||
<string name="keyboard_summary">Keyboard Settings</string>
|
||||
<string name="keyboard_switch_title">Toggle angle detection</string>
|
||||
<string name="keyboard_switch_summary">This toggles the angle detection of the keyboard</string>
|
||||
|
||||
</resources>
|
||||
|
||||
27
peripheralmanager/res/xml/keyboard_settings.xml
Normal file
27
peripheralmanager/res/xml/keyboard_settings.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The LineageOS Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/stylus_title">
|
||||
|
||||
<SwitchPreference
|
||||
android:key="keyboard_switch_key"
|
||||
android:defaultValue="true"
|
||||
android:title="@string/keyboard_switch_title"
|
||||
android:summary="@string/keyboard_switch_summary"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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()) + "] ";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user