From 371fc634d0cd580273c26dcda4d1129610c54134 Mon Sep 17 00:00:00 2001 From: SGCMarkus Date: Thu, 17 Feb 2022 11:26:56 +0100 Subject: [PATCH] sm8250-common: import lights aidl from https://github.com/LineageOS/android_device_motorola_nio e3a36424d4a7de739661061c3bd6fc2c5102da50 --- lights/Android.bp | 33 +++++ lights/Lights.cpp | 147 ++++++++++++++++++++ lights/Lights.h | 47 +++++++ lights/android.hardware.lights.motokona.rc | 11 ++ lights/android.hardware.lights.motokona.xml | 6 + lights/main.cpp | 37 +++++ sm8250.mk | 4 + 7 files changed, 285 insertions(+) create mode 100644 lights/Android.bp create mode 100644 lights/Lights.cpp create mode 100644 lights/Lights.h create mode 100644 lights/android.hardware.lights.motokona.rc create mode 100644 lights/android.hardware.lights.motokona.xml create mode 100644 lights/main.cpp diff --git a/lights/Android.bp b/lights/Android.bp new file mode 100644 index 0000000..6a89910 --- /dev/null +++ b/lights/Android.bp @@ -0,0 +1,33 @@ +// +// Copyright (C) 2019-2020 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. + +cc_binary { + name: "android.hardware.lights-service.motokona", + relative_install_path: "hw", + init_rc: ["android.hardware.lights.motokona.rc"], + vintf_fragments: ["android.hardware.lights.motokona.xml"], + vendor: true, + shared_libs: [ + "libbase", + "liblog", + "libhardware", + "libbinder_ndk", + "android.hardware.light-ndk_platform", + ], + srcs: [ + "Lights.cpp", + "main.cpp", + ], +} diff --git a/lights/Lights.cpp b/lights/Lights.cpp new file mode 100644 index 0000000..03543a3 --- /dev/null +++ b/lights/Lights.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020-2022 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. + */ + +#define LOG_TAG "android.hardware.lights-service.motokona" + +#include "Lights.h" +#include +#include + +/* clang-format off */ +#define PPCAT_NX(A, B) A/B +#define PPCAT(A, B) PPCAT_NX(A, B) +#define STRINGIFY_INNER(x) #x +#define STRINGIFY(x) STRINGIFY_INNER(x) + +#define CHARGING_ATTR(x) STRINGIFY(PPCAT(/sys/class/leds/charging, x)) +/* clang-format on */ + +namespace aidl { +namespace android { +namespace hardware { +namespace light { + +namespace { + +// Write value to path and close file. +template +inline bool WriteToFile(const std::string& path, T content) { + return ::android::base::WriteStringToFile(std::to_string(content), path); +} + +uint32_t RgbaToBrightness(uint32_t color) { + // Extract brightness from AARRGGBB. + uint32_t alpha = (color >> 24) & 0xFF; + + // Retrieve each of the RGB colors + uint32_t red = (color >> 16) & 0xFF; + uint32_t green = (color >> 8) & 0xFF; + uint32_t blue = color & 0xFF; + + // Scale RGB colors if a brightness has been applied by the user + if (alpha != 0xFF && alpha != 0) { + red = red * alpha / 0xFF; + green = green * alpha / 0xFF; + blue = blue * alpha / 0xFF; + } + + return (77 * red + 150 * green + 29 * blue) >> 8; +} + +inline bool IsLit(uint32_t color) { + return color & 0x00ffffff; +} + +void ApplyNotificationState(const HwLightState& state) { + bool blink = state.flashOnMs > 0 && state.flashOffMs > 0; + bool ok = false; + + switch (state.flashMode) { + case FlashMode::HARDWARE: + ok = WriteToFile(CHARGING_ATTR(breath), blink); + // fallback to timed blinking if breath is not supported + if (ok) break; + FALLTHROUGH_INTENDED; + case FlashMode::TIMED: + ok = WriteToFile(CHARGING_ATTR(delay_off), state.flashOffMs); + ok &= WriteToFile(CHARGING_ATTR(delay_on), state.flashOnMs); + // fallback to constant on if timed blinking is not supported + if (ok) break; + FALLTHROUGH_INTENDED; + case FlashMode::NONE: + default: + ok = WriteToFile(CHARGING_ATTR(brightness), RgbaToBrightness(state.color)); + break; + } + + LOG(DEBUG) << __func__ << ": mode=" << toString(state.flashMode) << ", colorRGB=" << std::hex + << state.color << std::dec << ", onMS=" << state.flashOnMs + << ", offMS=" << state.flashOffMs << ", ok=" << ok; +} + +} // anonymous namespace + +ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) { + static_assert(kAvailableLights.size() == std::tuple_size_v); + + if (id == static_cast(LightType::BACKLIGHT)) { + // Stub backlight handling + return ndk::ScopedAStatus::ok(); + } + + // Update saved state first + bool found = false; + for (size_t i = 0; i < notif_states_.size(); ++i) { + if (kAvailableLights[i].id == id) { + notif_states_[i] = state; + LOG(DEBUG) << __func__ << ": updating id=" << id + << ", type=" << toString(kAvailableLights[i].type); + found = true; + break; + } + } + if (!found) { + LOG(ERROR) << "Light not supported"; + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } + + // Lit up in order or fallback to battery light if others are dim + for (size_t i = 0; i < notif_states_.size(); ++i) { + auto&& cur_state = notif_states_[i]; + auto&& cur_light = kAvailableLights[i]; + if (IsLit(cur_state.color) || cur_light.type == LightType::BATTERY) { + LOG(DEBUG) << __func__ << ": applying id=" << cur_light.id + << ", type=" << toString(cur_light.type); + ApplyNotificationState(cur_state); + break; + } + } + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Lights::getLights(std::vector* lights) { + lights->insert(lights->end(), kAvailableLights.begin(), kAvailableLights.end()); + // We don't handle backlight but still need to report as supported. + lights->push_back({static_cast(LightType::BACKLIGHT), 0, LightType::BACKLIGHT}); + return ndk::ScopedAStatus::ok(); +} + +} // namespace light +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/lights/Lights.h b/lights/Lights.h new file mode 100644 index 0000000..323b878 --- /dev/null +++ b/lights/Lights.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2020-2022 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. + */ + +#pragma once + +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace light { + +// Keep sorted in the order of priority. +constexpr std::array kAvailableLights = { + // id, ordinal, type + HwLight{static_cast(LightType::NOTIFICATIONS), 0, LightType::NOTIFICATIONS}, + HwLight{static_cast(LightType::BATTERY), 0, LightType::BATTERY}, +}; + +class Lights : public BnLights { + public: + ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override; + ndk::ScopedAStatus getLights(std::vector* types) override; + + private: + std::array notif_states_; +}; + +} // namespace light +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/lights/android.hardware.lights.motokona.rc b/lights/android.hardware.lights.motokona.rc new file mode 100644 index 0000000..ee5539a --- /dev/null +++ b/lights/android.hardware.lights.motokona.rc @@ -0,0 +1,11 @@ +service vendor.light /vendor/bin/hw/android.hardware.lights-service.motokona + class hal + user system + group system + shutdown critical + +on boot + chown system system /sys/class/leds/charging/breath + chown system system /sys/class/leds/charging/brightness + chown system system /sys/class/leds/charging/delay_off + chown system system /sys/class/leds/charging/delay_on diff --git a/lights/android.hardware.lights.motokona.xml b/lights/android.hardware.lights.motokona.xml new file mode 100644 index 0000000..db604d6 --- /dev/null +++ b/lights/android.hardware.lights.motokona.xml @@ -0,0 +1,6 @@ + + + android.hardware.light + ILights/default + + diff --git a/lights/main.cpp b/lights/main.cpp new file mode 100644 index 0000000..8509bfb --- /dev/null +++ b/lights/main.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source 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. + */ + +#include +#include +#include +#include "Lights.h" + +using ::aidl::android::hardware::light::Lights; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr lights = ndk::SharedRefBase::make(); + if (!lights) { + return EXIT_FAILURE; + } + + const std::string instance = std::string() + Lights::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reached +} diff --git a/sm8250.mk b/sm8250.mk index 3491201..ac2fe8f 100644 --- a/sm8250.mk +++ b/sm8250.mk @@ -166,6 +166,10 @@ PRODUCT_PACKAGES += \ libipanat \ liboffloadhal +# Lights +PRODUCT_PACKAGES += \ + android.hardware.lights-service.motokona + # Media PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/media/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \