From 7a6ac36e65b875a06521ff97c6d453006943cb21 Mon Sep 17 00:00:00 2001 From: Demon000 Date: Tue, 14 May 2019 19:32:11 +0000 Subject: [PATCH] sm6250-common: import light HAL from Xiaomi msm8998-common Change-Id: Ieee4277f15927b4522deaec9a709809cf6db6fea --- light/Android.bp | 32 ++++ light/Light.cpp | 176 ++++++++++++++++++ light/Light.h | 68 +++++++ ...ardware.light@2.0-service.xiaomi_sm6250.rc | 17 ++ light/service.cpp | 50 +++++ sepolicy/vendor/file_contexts | 2 + 6 files changed, 345 insertions(+) create mode 100644 light/Android.bp create mode 100644 light/Light.cpp create mode 100644 light/Light.h create mode 100644 light/android.hardware.light@2.0-service.xiaomi_sm6250.rc create mode 100644 light/service.cpp create mode 100644 sepolicy/vendor/file_contexts diff --git a/light/Android.bp b/light/Android.bp new file mode 100644 index 0000000..600c8c7 --- /dev/null +++ b/light/Android.bp @@ -0,0 +1,32 @@ +// Copyright (C) 2019 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 { + relative_install_path: "hw", + defaults: ["hidl_defaults"], + name: "android.hardware.light@2.0-service.xiaomi_sm6250", + init_rc: ["android.hardware.light@2.0-service.xiaomi_sm6250.rc"], + srcs: ["service.cpp", "Light.cpp"], + vendor: true, + shared_libs: [ + "android.hardware.light@2.0", + "libbase", + "libhardware", + "libhidlbase", + "libhidltransport", + "libhwbinder", + "liblog", + "libutils", + ], +} diff --git a/light/Light.cpp b/light/Light.cpp new file mode 100644 index 0000000..54d05b3 --- /dev/null +++ b/light/Light.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2018-2019 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 "LightService" + +#include + +#include "Light.h" + +#include + +#define LCD_LED "/sys/class/backlight/panel0-backlight/" +#define WHITE_LED "/sys/class/leds/white/" + +#define BREATH "breath" +#define BRIGHTNESS "brightness" + +#define MAX_LED_BRIGHTNESS 255 +#define MAX_LCD_BRIGHTNESS 4095 + +namespace { +/* + * Write value to path and close file. + */ +static void set(std::string path, std::string value) { + std::ofstream file(path); + + if (!file.is_open()) { + ALOGW("failed to write %s to %s", value.c_str(), path.c_str()); + return; + } + + file << value; +} + +static void set(std::string path, int value) { + set(path, std::to_string(value)); +} + +static uint32_t getBrightness(const LightState& state) { + uint32_t alpha, red, green, blue; + + /* + * Extract brightness from AARRGGBB. + */ + alpha = (state.color >> 24) & 0xFF; + red = (state.color >> 16) & 0xFF; + green = (state.color >> 8) & 0xFF; + blue = state.color & 0xFF; + + /* + * Scale RGB brightness if Alpha brightness is not 0xFF. + */ + if (alpha != 0xFF) { + red = red * alpha / 0xFF; + green = green * alpha / 0xFF; + blue = blue * alpha / 0xFF; + } + + return (77 * red + 150 * green + 29 * blue) >> 8; +} + +static inline uint32_t scaleBrightness(uint32_t brightness, uint32_t maxBrightness) { + return brightness * maxBrightness / 0xFF; +} + +static inline uint32_t getScaledBrightness(const LightState& state, uint32_t maxBrightness) { + return scaleBrightness(getBrightness(state), maxBrightness); +} + +static void handleBacklight(const LightState& state) { + uint32_t brightness = getScaledBrightness(state, MAX_LCD_BRIGHTNESS); + set(LCD_LED BRIGHTNESS, brightness); +} + +static void handleNotification(const LightState& state) { + uint32_t whiteBrightness = getScaledBrightness(state, MAX_LED_BRIGHTNESS); + + /* Disable breathing or blinking */ + set(WHITE_LED BREATH, 0); + + switch (state.flashMode) { + case Flash::HARDWARE: + case Flash::TIMED: + /* Breathing */ + set(WHITE_LED BREATH, 1); + break; + case Flash::NONE: + default: + set(WHITE_LED BRIGHTNESS, whiteBrightness); + } +} + +static inline bool isLit(const LightState& state) { + return state.color & 0x00ffffff; +} + +/* Keep sorted in the order of importance. */ +static std::vector backends = { + { Type::ATTENTION, handleNotification }, + { Type::NOTIFICATIONS, handleNotification }, + { Type::BATTERY, handleNotification }, + { Type::BACKLIGHT, handleBacklight }, +}; + +} // anonymous namespace + +namespace android { +namespace hardware { +namespace light { +namespace V2_0 { +namespace implementation { + +Return Light::setLight(Type type, const LightState& state) { + LightStateHandler handler = nullptr; + + /* Lock global mutex until light state is updated. */ + std::lock_guard lock(globalLock); + + /* Update the cached state value for the current type. */ + for (LightBackend& backend : backends) { + if (backend.type == type) { + backend.state = state; + handler = backend.handler; + } + } + + /* If no handler has been found, then the type is not supported. */ + if (!handler) { + return Status::LIGHT_NOT_SUPPORTED; + } + + /* Light up the type with the highest priority that matches the current handler. */ + for (LightBackend& backend : backends) { + if (handler == backend.handler && isLit(backend.state)) { + handler(backend.state); + return Status::SUCCESS; + } + } + + /* If no type has been lit up, then turn off the hardware. */ + handler(state); + + return Status::SUCCESS; +} + +Return Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb) { + std::vector types; + + for (const LightBackend& backend : backends) { + types.push_back(backend.type); + } + + _hidl_cb(types); + + return Void(); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace light +} // namespace hardware +} // namespace android diff --git a/light/Light.h b/light/Light.h new file mode 100644 index 0000000..4f102d8 --- /dev/null +++ b/light/Light.h @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#ifndef ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H +#define ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H + +#include +#include +#include +#include +#include +#include + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::light::V2_0::Flash; +using ::android::hardware::light::V2_0::ILight; +using ::android::hardware::light::V2_0::LightState; +using ::android::hardware::light::V2_0::Status; +using ::android::hardware::light::V2_0::Type; + +typedef void (*LightStateHandler)(const LightState&); + +struct LightBackend { + Type type; + LightState state; + LightStateHandler handler; + + LightBackend(Type type, LightStateHandler handler) : type(type), handler(handler) { + this->state.color = 0xff000000; + } +}; + +namespace android { +namespace hardware { +namespace light { +namespace V2_0 { +namespace implementation { + +class Light : public ILight { + public: + Return setLight(Type type, const LightState& state) override; + Return getSupportedTypes(getSupportedTypes_cb _hidl_cb) override; + + private: + std::mutex globalLock; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace light +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H diff --git a/light/android.hardware.light@2.0-service.xiaomi_sm6250.rc b/light/android.hardware.light@2.0-service.xiaomi_sm6250.rc new file mode 100644 index 0000000..8675f51 --- /dev/null +++ b/light/android.hardware.light@2.0-service.xiaomi_sm6250.rc @@ -0,0 +1,17 @@ +on boot + chown system system /sys/class/backlight/panel0-backlight/brightness + chown system system /sys/class/backlight/panel0-backlight/max_brightness + chown system system /sys/class/leds/white/brightness + chown system system /sys/class/leds/white/breath + chmod 0644 /sys/class/backlight/panel0-backlight/brightness + chmod 0644 /sys/class/backlight/panel0-backlight/max_brightness + chmod 0644 /sys/class/leds/white/brightness + chmod 0644 /sys/class/leds/white/breath + +service vendor.light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service.xiaomi_sm6250 + interface android.hardware.light@2.0::ILight default + class hal + user system + group system + # shutting off lights while powering-off + shutdown critical diff --git a/light/service.cpp b/light/service.cpp new file mode 100644 index 0000000..7e5cf5f --- /dev/null +++ b/light/service.cpp @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#define LOG_TAG "android.hardware.light@2.0-service.xiaomi_sm6250" + +#include + +#include "Light.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; + +using android::hardware::light::V2_0::ILight; +using android::hardware::light::V2_0::implementation::Light; + +using android::OK; +using android::sp; +using android::status_t; + +int main() { + sp service = new Light(); + + configureRpcThreadpool(1, true); + + status_t status = service->registerAsService(); + if (status != OK) { + ALOGE("Cannot register Light HAL service."); + return 1; + } + + ALOGI("Light HAL service ready."); + + joinRpcThreadpool(); + + ALOGI("Light HAL service failed to join thread pool."); + return 1; +} diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts new file mode 100644 index 0000000..937e08e --- /dev/null +++ b/sepolicy/vendor/file_contexts @@ -0,0 +1,2 @@ +# HALs +/vendor/bin/hw/android\.hardware\.light@2\.0-service\.xiaomi_sm6250 u:object_r:hal_light_default_exec:s0