diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk index bf6aee9..a22ca0e 100644 --- a/BoardConfigCommon.mk +++ b/BoardConfigCommon.mk @@ -221,6 +221,10 @@ SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/private SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/public BOARD_VENDOR_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/vendor +# Sensors +TARGET_SENSOR_NOTIFIER_EXT ?= libsensor-notifier-ext +$(call soong_config_set, xiaomiSm8450SensorVars, extensionLibs, $(TARGET_SENSOR_NOTIFIER_EXT)) + # VINTF DEVICE_MATRIX_FILE := hardware/qcom-caf/common/compatibility_matrix.xml diff --git a/common.mk b/common.mk index 4cf9fd9..06d60e7 100644 --- a/common.mk +++ b/common.mk @@ -424,6 +424,9 @@ PRODUCT_PACKAGES += \ android.hardware.sensors@2.1-service.xiaomi-multihal \ android.frameworks.sensorservice@1.0.vendor +PRODUCT_PACKAGES += \ + sensor-notifier + $(foreach sku, taro diwali cape ukee, \ $(eval PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/sku_$(sku)/android.hardware.sensor.accelerometer.xml \ @@ -476,9 +479,6 @@ 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 index 4668f61..856e112 100644 --- a/sensors/Android.bp +++ b/sensors/Android.bp @@ -4,14 +4,45 @@ // SPDX-License-Identifier: Apache-2.0 // +soong_config_module_type { + name: "xiaomi_sm8450_sensor_notifier", + module_type: "cc_defaults", + config_namespace: "xiaomiSm8450SensorVars", + value_variables: ["extensionLibs"], + properties: [ + "whole_static_libs", + ], +} + +xiaomi_sm8450_sensor_notifier { + name: "xiaomi_sm8450_sensor_notifier_defaults", + soong_config_variables: { + extensionLibs: { + whole_static_libs: ["%s"], + }, + }, +} + +cc_library_headers { + name: "xiaomi_sm8450_sensor_notifier_headers", + export_include_dirs: ["include"], + vendor: true, +} + cc_binary { - name: "nonui-notifier", + name: "sensor-notifier", + defaults: [ + "xiaomi_sm8450_sensor_notifier_defaults", + ], vendor: true, - init_rc: ["nonui-notifier.rc"], + init_rc: ["sensor-notifier.rc"], srcs: [ - "NonUiNotifier.cpp", + "main.cpp", + "notifiers/NonUiNotifier.cpp", + "SensorNotifier.cpp", + "utils/SensorNotifierUtils.cpp", ], shared_libs: [ @@ -23,5 +54,23 @@ cc_binary { header_libs: [ "generated_kernel_headers", + "xiaomi_sm8450_sensor_notifier_headers", + ], +} + +cc_library_static { + name: "libsensor-notifier-ext", + vendor: true, + + srcs: [ + "SensorNotifierExt.cpp", + ], + + shared_libs: [ + "android.frameworks.sensorservice@1.0", + ], + + header_libs: [ + "xiaomi_sm8450_sensor_notifier_headers", ], } diff --git a/sensors/NonUiNotifier.cpp b/sensors/NonUiNotifier.cpp deleted file mode 100644 index a829ba7..0000000 --- a/sensors/NonUiNotifier.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2024 The LineageOS Project - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define LOG_TAG "NonUiNotifier" - -#include -#include - -#include -#include -#include - -#include - -#define SENSOR_NAME_XIAOMI_SENSOR_NONUI "xiaomi.sensor.nonui" - -using android::sp; -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::SensorFlagBits; -using android::hardware::sensors::V1_0::SensorInfo; -using android::hardware::sensors::V1_0::SensorType; - -#define TOUCH_DEV_PATH "/dev/xiaomi-touch" - -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) { - int touchFd = open(TOUCH_DEV_PATH, O_RDWR); - if (touchFd == -1) { - LOG(ERROR) << "failed to open " << TOUCH_DEV_PATH; - return Void(); - } - - int buf[MAX_BUF_SIZE] = {0, Touch_Nonui_Mode, static_cast(e.u.scalar)}; - ioctl(touchFd, TOUCH_IOC_SET_CUR_VALUE, &buf); - close(touchFd); - - return Void(); - } -}; - -} // namespace - -int main() { - Result res; - sp queue; - - sp manager = ISensorManager::getService(); - if (manager == nullptr) { - LOG(ERROR) << "failed to get ISensorManager"; - return EXIT_FAILURE; - } - - std::vector sensorList; - manager->getSensorList([&sensorList, &res](const auto& l, auto r) { - sensorList = l; - res = r; - }); - if (res != Result::OK) { - LOG(ERROR) << "failed to get getSensorList"; - return EXIT_FAILURE; - } - auto it = std::find_if(sensorList.begin(), sensorList.end(), [](const SensorInfo& sensor) { - return (sensor.typeAsString == SENSOR_NAME_XIAOMI_SENSOR_NONUI) && - (sensor.flags & SensorFlagBits::WAKE_UP); - }); - - int32_t sensorHandle = -1; - if (it != sensorList.end()) { - sensorHandle = it->sensorHandle; - } else { - LOG(ERROR) << "failed to get wake-up version of nonui sensor"; - return EXIT_FAILURE; - } - - sensorList.clear(); - - manager->createEventQueue(new NonUiSensorCallback(), [&queue, &res](const auto& q, auto r) { - queue = q; - res = r; - }); - if (res != Result::OK) { - LOG(ERROR) << "failed to create event queue"; - 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); - 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(VERBOSE) << "polled change on " << paths[i]; - } - } - - bool enabled = false; - for (size_t i = 0; i < paths.size(); ++i) { - enabled = enabled || readBool(pollfds[i].fd); - } - 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/SensorNotifier.cpp b/sensors/SensorNotifier.cpp new file mode 100644 index 0000000..d294a51 --- /dev/null +++ b/sensors/SensorNotifier.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "SensorNotifier" + +#include "SensorNotifier.h" + +#include + +using android::hardware::sensors::V1_0::SensorFlagBits; +using android::hardware::sensors::V1_0::SensorInfo; + +SensorNotifier::SensorNotifier(sp manager) : mManager(manager) {} + +SensorNotifier::~SensorNotifier() { + if (mQueue != nullptr) { + /* + * Free the event queue. + * kernel calls decStrong() on server side implementation of IEventQueue, + * hence resources (including the callback) are freed as well. + */ + mQueue = nullptr; + } +} + +Result SensorNotifier::initializeSensorQueue(std::string typeAsString, bool wakeup, + sp callback) { + Result res; + std::vector sensorList; + + mManager->getSensorList([&sensorList, &res](const auto& l, auto r) { + sensorList = l; + res = r; + }); + if (res != Result::OK) { + LOG(ERROR) << "failed to get sensors list"; + return res; + } + auto it = std::find_if(sensorList.begin(), sensorList.end(), + [this, &typeAsString, &wakeup](const SensorInfo& sensor) { + return (sensor.typeAsString == typeAsString) && + ((sensor.flags & SensorFlagBits::WAKE_UP) == wakeup); + }); + + if (it != sensorList.end()) { + mSensorHandle = it->sensorHandle; + } else { + LOG(ERROR) << "failed to get " << typeAsString << " sensor with wake-up: " << wakeup; + return Result::NOT_EXIST; + } + + mManager->createEventQueue(callback, [this, &res](const auto& q, auto r) { + this->mQueue = q; + res = r; + }); + if (res != Result::OK) { + LOG(ERROR) << "failed to create event queue"; + return res; + } + + return Result::OK; +} + +void SensorNotifier::activate() { + if (mActive) { + return; + } + mActive = true; + mThread = std::thread(&SensorNotifier::notify, this); +} + +void SensorNotifier::deactivate() { + if (!mActive) { + return; + } + mActive = false; + if (mThread.joinable()) { + mThread.join(); + } + if (mQueue != nullptr) { + mQueue->disableSensor(mSensorHandle); + } +} diff --git a/sensors/SensorNotifierExt.cpp b/sensors/SensorNotifierExt.cpp new file mode 100644 index 0000000..98cb68c --- /dev/null +++ b/sensors/SensorNotifierExt.cpp @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "SensorNotifierExt.h" + +SensorNotifierExt::SensorNotifierExt(sp /* manager */) {} diff --git a/sensors/include/SensorNotifier.h b/sensors/include/SensorNotifier.h new file mode 100644 index 0000000..acd862c --- /dev/null +++ b/sensors/include/SensorNotifier.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +using android::sp; +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; + +class SensorNotifier { + public: + SensorNotifier(sp manager); + virtual ~SensorNotifier(); + + void activate(); + void deactivate(); + + protected: + Result initializeSensorQueue(std::string typeAsString, bool wakeup, sp); + virtual void notify() = 0; + + sp mQueue; + int32_t mSensorHandle = -1; + bool mActive = false; + + private: + sp mManager; + std::thread mThread; +}; diff --git a/sensors/include/SensorNotifierExt.h b/sensors/include/SensorNotifierExt.h new file mode 100644 index 0000000..0115221 --- /dev/null +++ b/sensors/include/SensorNotifierExt.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "SensorNotifier.h" + +using android::sp; +using android::frameworks::sensorservice::V1_0::ISensorManager; + +class SensorNotifierExt { + public: + SensorNotifierExt(sp manager); + std::vector> mNotifiers; +}; diff --git a/sensors/include/SensorNotifierUtils.h b/sensors/include/SensorNotifierUtils.h new file mode 100644 index 0000000..400e9d4 --- /dev/null +++ b/sensors/include/SensorNotifierUtils.h @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +bool readBool(int fd); diff --git a/sensors/main.cpp b/sensors/main.cpp new file mode 100644 index 0000000..2b094e5 --- /dev/null +++ b/sensors/main.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "SensorNotifier" + +#include +#include + +#include "SensorNotifierExt.h" +#include "notifiers/NonUiNotifier.h" + +int main() { + sp manager = ISensorManager::getService(); + if (manager == nullptr) { + LOG(ERROR) << "failed to get ISensorManager"; + return EXIT_FAILURE; + } + + std::vector> notifiers; + notifiers.push_back(std::make_unique(manager)); + for (const auto& notifier : notifiers) { + notifier->activate(); + } + + std::unique_ptr sensorNotifierExt = + std::make_unique(manager); + for (const auto& notifier : sensorNotifierExt->mNotifiers) { + notifier->activate(); + } + + while (true) { + // Sleep to keep the notifiers alive + std::this_thread::sleep_for(std::chrono::seconds(10)); + } + + // Should never reach this + return EXIT_SUCCESS; +} diff --git a/sensors/notifiers/NonUiNotifier.cpp b/sensors/notifiers/NonUiNotifier.cpp new file mode 100644 index 0000000..e7b45ba --- /dev/null +++ b/sensors/notifiers/NonUiNotifier.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "NonUiNotifier" + +#include "NonUiNotifier.h" + +#include +#include +#include +#include +#include + +#include "SensorNotifierUtils.h" + +static const std::string kTouchDevice = "/dev/xiaomi-touch"; + +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::sensors::V1_0::Event; + +namespace { + +class NonUiSensorCallback : public IEventQueueCallback { + public: + NonUiSensorCallback() { + touch_fd_ = android::base::unique_fd(open(kTouchDevice.c_str(), O_RDWR)); + if (touch_fd_.get() == -1) { + LOG(ERROR) << "failed to open " << kTouchDevice; + } + } + + Return onEvent(const Event& e) { + int buf[MAX_BUF_SIZE] = {0, Touch_Nonui_Mode, static_cast(e.u.scalar)}; + ioctl(touch_fd_.get(), TOUCH_IOC_SET_CUR_VALUE, &buf); + + return Void(); + } + + private: + android::base::unique_fd touch_fd_; +}; + +} // namespace + +NonUiNotifier::NonUiNotifier(sp manager) : SensorNotifier(manager) { + initializeSensorQueue("xiaomi.sensor.nonui", true, new NonUiSensorCallback()); +} + +NonUiNotifier::~NonUiNotifier() { + deactivate(); +} + +void NonUiNotifier::notify() { + Result res; + + // 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; + mActive = false; + return; + } + + pollfds[i].fd = fd; + pollfds[i].events = POLLPRI; + } + + while (mActive) { + int rc = poll(pollfds, paths.size(), -1); + if (rc < 0) { + LOG(ERROR) << "failed to poll, err: " << rc; + continue; + } + + bool enabled = false; + for (size_t i = 0; i < paths.size(); ++i) { + enabled = enabled || readBool(pollfds[i].fd); + } + if (enabled) { + res = mQueue->enableSensor(mSensorHandle, 20000 /* sample period */, 0 /* latency */); + if (res != Result::OK) { + LOG(ERROR) << "failed to enable sensor"; + } + } else { + res = mQueue->disableSensor(mSensorHandle); + if (res != Result::OK) { + LOG(DEBUG) << "failed to disable sensor"; + } + } + } +} diff --git a/sensors/notifiers/NonUiNotifier.h b/sensors/notifiers/NonUiNotifier.h new file mode 100644 index 0000000..8ddc3c0 --- /dev/null +++ b/sensors/notifiers/NonUiNotifier.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "SensorNotifier.h" + +class NonUiNotifier : public SensorNotifier { + public: + NonUiNotifier(sp manager); + ~NonUiNotifier(); + + protected: + void notify(); +}; diff --git a/sensors/nonui-notifier.rc b/sensors/sensor-notifier.rc similarity index 69% rename from sensors/nonui-notifier.rc rename to sensors/sensor-notifier.rc index c9d84e0..8def26f 100644 --- a/sensors/nonui-notifier.rc +++ b/sensors/sensor-notifier.rc @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # -service vendor.nonui-notifier /vendor/bin/nonui-notifier +service vendor.sensor-notifier /vendor/bin/sensor-notifier class main user system group system diff --git a/sensors/utils/SensorNotifierUtils.cpp b/sensors/utils/SensorNotifierUtils.cpp new file mode 100644 index 0000000..5775fd6 --- /dev/null +++ b/sensors/utils/SensorNotifierUtils.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "SensorNotifierUtils" + +#include "SensorNotifierUtils.h" + +#include + +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'; +} diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts index 3d1f807..5030780 100644 --- a/sepolicy/vendor/file_contexts +++ b/sepolicy/vendor/file_contexts @@ -81,7 +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 +/(vendor|system/vendor)/bin/sensor-notifier u:object_r:vendor_sensor_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 deleted file mode 100644 index 374f9d6..0000000 --- a/sepolicy/vendor/vendor_nonui_notifier.te +++ /dev/null @@ -1,17 +0,0 @@ -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) diff --git a/sepolicy/vendor/vendor_sensor_notifier.te b/sepolicy/vendor/vendor_sensor_notifier.te new file mode 100644 index 0000000..d7d4a77 --- /dev/null +++ b/sepolicy/vendor/vendor_sensor_notifier.te @@ -0,0 +1,17 @@ +type vendor_sensor_notifier, domain; +type vendor_sensor_notifier_exec, exec_type, file_type, vendor_file_type; + +init_daemon_domain(vendor_sensor_notifier) + +hwbinder_use(vendor_sensor_notifier) + +# for sensor callbacks +binder_use(vendor_sensor_notifier) +binder_call(vendor_sensor_notifier, system_server) +binder_call(system_server, vendor_sensor_notifier) + +allow vendor_sensor_notifier fwk_sensor_hwservice:hwservice_manager find; +allow vendor_sensor_notifier touchfeature_device:chr_file rw_file_perms; +allow vendor_sensor_notifier vendor_sysfs_sensors:file r_file_perms; + +get_prop(vendor_sensor_notifier, hwservicemanager_prop)