diff --git a/common.mk b/common.mk index 5f9376c..bbd5f5e 100644 --- a/common.mk +++ b/common.mk @@ -462,6 +462,9 @@ PRODUCT_PACKAGES += \ android.hardware.thermal@2.0-service.qti-v2 # Touchscreen +PRODUCT_PACKAGES += \ + nonui-notifier + PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml diff --git a/sensors/Android.bp b/sensors/Android.bp new file mode 100644 index 0000000..b45058e --- /dev/null +++ b/sensors/Android.bp @@ -0,0 +1,29 @@ +// +// Copyright (C) 2024 The LineageOS Project +// +// SPDX-License-Identifier: Apache-2.0 +// + +cc_binary { + name: "nonui-notifier", + vendor: true, + + init_rc: ["nonui-notifier.rc"], + + srcs: [ + "NonUiNotifier.cpp", + ], + + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "libutils", + "android.frameworks.sensorservice@1.0", + "android.hardware.sensors@1.0", + ], + + header_libs: [ + "generated_kernel_headers", + ], +} diff --git a/sensors/NonUiNotifier.cpp b/sensors/NonUiNotifier.cpp new file mode 100644 index 0000000..fc119fe --- /dev/null +++ b/sensors/NonUiNotifier.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "NonUiNotifier" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "xiaomi_touch.h" + +#define SENSOR_TYPE_XIAOMI_SENSOR_NONUI 33171027 +#define SENSOR_NAME_XIAOMI_SENSOR_NONUI "xiaomi.sensor.nonui" + +using ::android::frameworks::sensorservice::V1_0::IEventQueue; +using ::android::frameworks::sensorservice::V1_0::IEventQueueCallback; +using ::android::frameworks::sensorservice::V1_0::ISensorManager; +using ::android::frameworks::sensorservice::V1_0::Result; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::sensors::V1_0::Event; +using ::android::hardware::sensors::V1_0::SensorType; + +using android::sp; + +#define TOUCH_DEV_PATH "/dev/xiaomi-touch" +#define TOUCH_MAGIC 'T' +#define TOUCH_IOC_SET_CUR_VALUE _IO(TOUCH_MAGIC, SET_CUR_VALUE) +#define TOUCH_IOC_GET_CUR_VALUE _IO(TOUCH_MAGIC, GET_CUR_VALUE) + +namespace { + +static bool readBool(int fd) { + char c; + int rc; + + rc = lseek(fd, 0, SEEK_SET); + if (rc) { + LOG(ERROR) << "failed to seek fd, err: " << rc; + return false; + } + + rc = read(fd, &c, sizeof(char)); + if (rc != 1) { + LOG(ERROR) << "failed to read bool from fd, err: " << rc; + return false; + } + + return c != '0'; +} + +struct NonUiSensorCallback : IEventQueueCallback { + Return onEvent(const Event& e) { + /* handle sensor event e */ + LOG(ERROR) << "onEvent scalar: " << e.u.scalar; + bool nonUi = e.u.scalar == 1; + + // android::base::unique_fd touch_fd_; + // touch_fd_ = android::base::unique_fd(open(TOUCH_DEV_PATH, O_RDWR)); + + int buf[MAX_BUF_SIZE] = {0, Touch_Nonui_Mode, nonUi ? 2 : 0}; + ioctl(open(TOUCH_DEV_PATH, O_RDWR), TOUCH_IOC_SET_CUR_VALUE, &buf); + + return Void(); + } +}; + +} // namespace + +int main() { + sp manager = ISensorManager::getService(); + if (manager == nullptr) { + LOG(ERROR) << "failed to get ISensorManager"; + } + + int32_t sensorHandle = -1; + manager->getDefaultSensor(static_cast(SENSOR_TYPE_XIAOMI_SENSOR_NONUI), + [&sensorHandle](const auto& info, auto r) { + sensorHandle = info.sensorHandle; + }); + + sp queue; + Result res; + manager->createEventQueue(new NonUiSensorCallback(), [&queue, &res](const auto& q, auto r) { + queue = q; + res = r; + }); + if (res != Result::OK) { + return EXIT_FAILURE; + } + + // Enable states of touchscreen sensors + const std::vector paths = { + "/sys/class/touch/touch_dev/fod_longpress_gesture_enabled", + "/sys/class/touch/touch_dev/gesture_single_tap_enabled", + "/sys/class/touch/touch_dev/gesture_double_tap_enabled"}; + + pollfd* pollfds = new pollfd[paths.size()]; + for (size_t i = 0; i < paths.size(); ++i) { + int fd = open(paths[i], O_RDONLY); + if (fd < 0) { + LOG(ERROR) << "failed to open " << paths[i] << " , err: " << fd; + return EXIT_FAILURE; + } + + pollfds[i].fd = fd; + pollfds[i].events = POLLERR | POLLPRI; + pollfds[i].revents = 0; + } + + while (true) { + int rc = poll(pollfds, paths.size(), -1); + LOG(ERROR) << "poll: " << rc; + if (rc < 0) { + LOG(ERROR) << "failed to poll, err: " << rc; + continue; + } + + for (size_t i = 0; i < paths.size(); ++i) { + if (pollfds[i].revents & (POLLERR | POLLPRI)) { + LOG(ERROR) << "Event on " << paths[i]; + } + } + + bool enabled = false; + for (size_t i = 0; i < paths.size(); ++i) { + enabled = enabled || readBool(pollfds[i].fd); + } + LOG(ERROR) << "got notified about poll, enabled: " << enabled; + if (enabled) { + res = queue->enableSensor(sensorHandle, 20000 /* sample period */, 0 /* latency */); + if (res != Result::OK) { + LOG(ERROR) << "failed to enable sensor"; + } + } else { + res = queue->disableSensor(sensorHandle); + if (res != Result::OK) { + LOG(ERROR) << "failed to disable sensor"; + } + } + } + + /* + * Free the event queue. + * kernel calls decStrong() on server side implementation of IEventQueue, + * hence resources (including the callback) are freed as well. + */ + queue = nullptr; + + // Should never reach this + return EXIT_SUCCESS; +} diff --git a/sensors/nonui-notifier.rc b/sensors/nonui-notifier.rc new file mode 100644 index 0000000..c9d84e0 --- /dev/null +++ b/sensors/nonui-notifier.rc @@ -0,0 +1,10 @@ +# +# Copyright (C) 2024 The LineageOS Project +# +# SPDX-License-Identifier: Apache-2.0 +# + +service vendor.nonui-notifier /vendor/bin/nonui-notifier + class main + user system + group system diff --git a/sensors/xiaomi_touch.h b/sensors/xiaomi_touch.h new file mode 100644 index 0000000..14bddfa --- /dev/null +++ b/sensors/xiaomi_touch.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/*CUR,DEFAULT,MIN,MAX*/ +#define VALUE_TYPE_SIZE 6 +#define VALUE_GRIP_SIZE 9 +#define MAX_BUF_SIZE 256 +#define BTN_INFO 0x152 +#define MAX_TOUCH_ID 10 +#define RAW_BUF_NUM 4 +#define THP_CMD_BASE 1000 + +enum MODE_CMD { + SET_CUR_VALUE = 0, + GET_CUR_VALUE, + GET_DEF_VALUE, + GET_MIN_VALUE, + GET_MAX_VALUE, + GET_MODE_VALUE, + RESET_MODE, + SET_LONG_VALUE, +}; + +enum MODE_TYPE { + Touch_Game_Mode = 0, + Touch_Active_MODE = 1, + Touch_UP_THRESHOLD = 2, + Touch_Tolerance = 3, + Touch_Aim_Sensitivity = 4, + Touch_Tap_Stability = 5, + Touch_Expert_Mode = 6, + Touch_Edge_Filter = 7, + Touch_Panel_Orientation = 8, + Touch_Report_Rate = 9, + Touch_Fod_Enable = 10, + Touch_Aod_Enable = 11, + Touch_Resist_RF = 12, + Touch_Idle_Time = 13, + Touch_Doubletap_Mode = 14, + Touch_Grip_Mode = 15, + Touch_FodIcon_Enable = 16, + Touch_Nonui_Mode = 17, + Touch_Debug_Level = 18, + Touch_Power_Status = 19, + Touch_Mode_NUM = 20, + THP_LOCK_SCAN_MODE = THP_CMD_BASE + 0, + THP_FOD_DOWNUP_CTL = THP_CMD_BASE + 1, + THP_SELF_CAP_SCAN = THP_CMD_BASE + 2, + THP_REPORT_POINT_SWITCH = THP_CMD_BASE + 3, + THP_HAL_INIT_READY = THP_CMD_BASE + 4, +}; diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts index 131e77c..3d1f807 100644 --- a/sepolicy/vendor/file_contexts +++ b/sepolicy/vendor/file_contexts @@ -81,6 +81,7 @@ # Sensors /(vendor|system/vendor)/bin/hw/android\.hardware\.sensors@2.1-service\.xiaomi-multihal u:object_r:hal_sensors_default_exec:s0 /(vendor|system/vendor)/bin/hw/vendor.xiaomi.sensor.communicate@1.0-service u:object_r:vendor_hal_sensorcommunicate_default_exec:s0 +/(vendor|system/vendor)/bin/nonui-notifier u:object_r:vendor_nonui_notifier_exec:s0 /dev/stmvl53l5 u:object_r:stmvl53l5_device:s0 # Thermal diff --git a/sepolicy/vendor/vendor_nonui_notifier.te b/sepolicy/vendor/vendor_nonui_notifier.te new file mode 100644 index 0000000..374f9d6 --- /dev/null +++ b/sepolicy/vendor/vendor_nonui_notifier.te @@ -0,0 +1,17 @@ +type vendor_nonui_notifier, domain; +type vendor_nonui_notifier_exec, exec_type, file_type, vendor_file_type; + +init_daemon_domain(vendor_nonui_notifier) + +hwbinder_use(vendor_nonui_notifier) + +# for sensor callbacks +binder_use(vendor_nonui_notifier) +binder_call(vendor_nonui_notifier, system_server) +binder_call(system_server, vendor_nonui_notifier) + +allow vendor_nonui_notifier fwk_sensor_hwservice:hwservice_manager find; +allow vendor_nonui_notifier touchfeature_device:chr_file rw_file_perms; +allow vendor_nonui_notifier vendor_sysfs_sensors:file r_file_perms; + +get_prop(vendor_nonui_notifier, hwservicemanager_prop)