From c1ab176762c12231f882008aaad45767b629d15d Mon Sep 17 00:00:00 2001 From: Max Weffers Date: Tue, 6 Aug 2019 21:43:10 +0200 Subject: [PATCH] sdm660-common : Adapt xiaomi msm8998 Light hal for sdm660 --- light/Light.cpp | 233 +++++++++++++++++++++++++++------------------- light/Light.h | 46 +++++---- light/service.cpp | 2 +- 3 files changed, 167 insertions(+), 114 deletions(-) diff --git a/light/Light.cpp b/light/Light.cpp index c62bc331..9e284a79 100644 --- a/light/Light.cpp +++ b/light/Light.cpp @@ -14,37 +14,34 @@ * limitations under the License. */ -//Author := dev_harsh1998, Isaac Chen - #define LOG_TAG "android.hardware.light@2.0-service.xiaomi_sdm660" #include -#include + #include "Light.h" -namespace android { -namespace hardware { -namespace light { -namespace V2_0 { -namespace implementation { +#include -#define LEDS "/sys/class/leds/" -#define LCD_LED LEDS "lcd-backlight/" -#define BRIGHTNESS "brightness" -#define RED LEDS "red/" -#define BLINK "blink" -#define DUTY_PCTS "duty_pcts" -#define PAUSE_HI "pause_hi" -#define PAUSE_LO "pause_lo" -#define RAMP_STEP_MS "ramp_step_ms" -#define START_IDX "start_idx" +#define LEDS "/sys/class/leds/" + +#define LCD_LED LEDS "lcd-backlight/" +#define WHITE_LED LEDS "red/" + +#define BLINK "blink" +#define BRIGHTNESS "brightness" +#define MAX_BRIGHTNESS "max_brightness" +#define DUTY_PCTS "duty_pcts" +#define PAUSE_HI "pause_hi" +#define PAUSE_LO "pause_lo" +#define RAMP_STEP_MS "ramp_step_ms" +#define START_IDX "start_idx" /* - * 8 duty percent steps. + * 15 duty percent steps. */ #define RAMP_STEPS 15 /* - * Each step will stay on for 50ms by default. + * Each step will stay on for 150ms by default. */ #define RAMP_STEP_DURATION 150 /* @@ -52,25 +49,80 @@ namespace implementation { */ static int32_t BRIGHTNESS_RAMP[RAMP_STEPS] = {0, 12, 25, 37, 50, 72, 85, 100, 85, 72, 50, 37, 25, 12, 0}; +namespace { /* * Write value to path and close file. */ static void set(std::string path, std::string value) { std::ofstream file(path); - /* Only write brightness value if stream is open, alive & well */ - if (file.is_open()) { - file << value; - } else { - /* Fire a warning a bail out */ - ALOGE("failed to write %s to %s", value.c_str(), path.c_str()); + + 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 int get(std::string path) { + std::ifstream file(path); + int value; + + if (!file.is_open()) { + ALOGW("failed to read from %s", path.c_str()); + return 0; + } + + file >> value; + return value; +} + +static int getMaxBrightness(std::string path) { + int value = get(path); + ALOGW("Got max brightness %d", value); + return 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, getMaxBrightness(LCD_LED MAX_BRIGHTNESS)); + set(LCD_LED BRIGHTNESS, brightness); +} + /* * Scale each value of the brightness ramp according to the * brightness of the color. @@ -86,54 +138,38 @@ static std::string getScaledRamp(uint32_t brightness) { return ramp; } -static void handleWayneBacklight(Type /*type*/, const LightState& state) { - uint32_t brightness = state.color & 0xFF; - set(LCD_LED BRIGHTNESS, brightness); -} +static void handleNotification(const LightState& state) { + uint32_t whiteBrightness = getScaledBrightness(state, getMaxBrightness(WHITE_LED MAX_BRIGHTNESS)); -static void setNotification(const LightState& state) { - uint32_t redBrightness, brightness; - - /* - * Extract brightness from RGB. - */ - redBrightness = (state.color >> 16) & 0xFF; - brightness = (state.color >> 24) & 0xFF; - - /* - * Scale RGB brightness if the Alpha brightness is not 0xFF. - */ - if (brightness != 0xFF) { - redBrightness = (redBrightness * brightness) / 0xFF; - } - - /* Turn off the leds (initially) */ - set(RED BRIGHTNESS, 0); - set(RED BLINK, 0); + /* Disable blinking */ + set(WHITE_LED BLINK, 0); if (state.flashMode == Flash::TIMED) { /* * If the flashOnMs duration is not long enough to fit ramping up * and down at the default step duration, step duration is modified * to fit. - */ + */ int32_t stepDuration = RAMP_STEP_DURATION; int32_t pauseHi = state.flashOnMs - (stepDuration * RAMP_STEPS * 2); int32_t pauseLo = state.flashOffMs; if (pauseHi < 0) { + //stepDuration = state.flashOnMs / (RAMP_STEPS * 2); pauseHi = 0; } - /* Red(Actually White) */ - set(RED BLINK, 1); - set(RED START_IDX, 0 * RAMP_STEPS); - set(RED DUTY_PCTS, getScaledRamp(redBrightness)); - set(RED PAUSE_LO, pauseLo); - set(RED PAUSE_HI, pauseHi); - set(RED RAMP_STEP_MS, stepDuration); + /* White */ + set(WHITE_LED START_IDX, 0 * RAMP_STEPS); + set(WHITE_LED DUTY_PCTS, getScaledRamp(whiteBrightness)); + set(WHITE_LED PAUSE_LO, pauseLo); + set(WHITE_LED PAUSE_HI, pauseHi); + set(WHITE_LED RAMP_STEP_MS, stepDuration); + + /* Enable blinking */ + set(WHITE_LED BLINK, 1); } else { - set(RED BRIGHTNESS, redBrightness); + set(WHITE_LED BRIGHTNESS, whiteBrightness); } } @@ -141,60 +177,65 @@ static inline bool isLit(const LightState& state) { return state.color & 0x00ffffff; } -/* - * Keep sorted in the order of importance. - */ -static const LightState offState = {}; -static std::vector> notificationStates = { - { Type::ATTENTION, offState }, - { Type::NOTIFICATIONS, offState }, - { Type::BATTERY, offState }, +/* Keep sorted in the order of importance. */ +static std::vector backends = { + { Type::ATTENTION, handleNotification }, + { Type::NOTIFICATIONS, handleNotification }, + { Type::BATTERY, handleNotification }, + { Type::BACKLIGHT, handleBacklight }, }; -static void handleWayneNotification(Type type, const LightState& state) { - for(auto it : notificationStates) { - if (it.first == type) { - it.second = state; - } +} // anonymous namespace - if (isLit(it.second)) { - setNotification(it.second); - return; +namespace android { +namespace hardware { +namespace light { +namespace V2_0 { +namespace implementation { + +Return Light::setLight(Type type, const LightState& state) { + LightStateHandler handler; + bool handled = false; + + /* 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; } } - setNotification(offState); -} - -static std::map> lights = { - {Type::BACKLIGHT, handleWayneBacklight}, - {Type::NOTIFICATIONS, handleWayneNotification}, - {Type::BATTERY, handleWayneNotification}, - {Type::ATTENTION, handleWayneNotification}, -}; - -Light::Light() {} - -Return Light::setLight(Type type, const LightState& state) { - auto it = lights.find(type); - - if (it == lights.end()) { + /* If no handler has been found, then the type is not supported. */ + if (!handler) { return Status::LIGHT_NOT_SUPPORTED; } - /* - * Lock global mutex until light state is updated. - */ + /* 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); + handled = true; + break; + } + } + + /* If no type has been lit up, then turn off the hardware. */ + if (!handled) { + handler(state); + } - std::lock_guard lock(globalLock); - it->second(type, state); return Status::SUCCESS; } Return Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb) { std::vector types; - for (auto const& light : lights) types.push_back(light.first); + for (const LightBackend& backend : backends) { + types.push_back(backend.type); + } _hidl_cb(types); diff --git a/light/Light.h b/light/Light.h index 311b7ded..f8026818 100644 --- a/light/Light.h +++ b/light/Light.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The LineageOS Project + * Copyright (C) 2018 The Xiaomi-SDM660 Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ * 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 @@ -21,6 +22,27 @@ #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 { @@ -28,23 +50,13 @@ namespace light { namespace V2_0 { namespace implementation { -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::hardware::hidl_vec; -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; - class Light : public ILight { - public: - Light(); + public: + Return setLight(Type type, const LightState& state) override; + Return getSupportedTypes(getSupportedTypes_cb _hidl_cb) override; - Return setLight(Type type, const LightState& state) override; - Return getSupportedTypes(getSupportedTypes_cb _hidl_cb) override; - - private: - std::mutex globalLock; + private: + std::mutex globalLock; }; } // namespace implementation @@ -53,4 +65,4 @@ class Light : public ILight { } // namespace hardware } // namespace android -#endif // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H +#endif // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H \ No newline at end of file diff --git a/light/service.cpp b/light/service.cpp index 8f6fa889..b8e699f0 100644 --- a/light/service.cpp +++ b/light/service.cpp @@ -31,7 +31,7 @@ using android::sp; using android::status_t; int main() { - android::sp service = new Light(); + sp service = new Light(); configureRpcThreadpool(1, true);