summaryrefslogtreecommitdiff
path: root/light/Light.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'light/Light.cpp')
-rw-r--r--light/Light.cpp275
1 files changed, 129 insertions, 146 deletions
diff --git a/light/Light.cpp b/light/Light.cpp
index e6d9349..0286b6a 100644
--- a/light/Light.cpp
+++ b/light/Light.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 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.
@@ -14,80 +15,59 @@
* limitations under the License.
*/
-//Author := dev_harsh1998, Isaac Chen
+// Author := dev_harsh1998, Isaac Chen
-#define LOG_TAG "android.hardware.light@2.0-service.xiaomi_sdm660"
+#define LOG_TAG "android.hardware.light@2.0-impl.xiaomi_sdm660"
+/* #define LOG_NDEBUG 0 */
-#include <log/log.h>
-#include <fstream>
#include "Light.h"
-namespace android {
-namespace hardware {
-namespace light {
-namespace V2_0 {
-namespace implementation {
+#include <android-base/file.h>
+#include <android-base/logging.h>
-#define LEDS "/sys/class/leds/"
-#define LCD_LED LEDS "lcd-backlight/"
-#define BRIGHTNESS "brightness"
-#define WHITE LEDS "white/"
-#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"
+namespace {
-#define MAX_LED_BRIGHTNESS 255
-#define MAX_LCD_BRIGHTNESS 4095
+#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)
-/*
- * 8 duty percent steps.
- */
-#define RAMP_STEPS 8
-/*
- * Each step will stay on for 50ms by default.
- */
-#define RAMP_STEP_DURATION 50
-/*
- * Each value represents a duty percent (0 - 100) for the led pwm.
- */
-static int32_t BRIGHTNESS_RAMP[RAMP_STEPS] = {0, 12, 25, 37, 50, 72, 85, 100};
+#define LEDS(x) PPCAT(/sys/class/leds, x)
+#define LCD_ATTR(x) STRINGIFY(PPCAT(LEDS(lcd-backlight), x))
+#define WHITE_ATTR(x) STRINGIFY(PPCAT(LEDS(white), x))
-/*
- * 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());
- return;
- }
+using ::android::base::ReadFileToString;
+using ::android::base::WriteStringToFile;
+
+// Default max brightness
+constexpr auto kDefaultMaxLedBrightness = 255;
+constexpr auto kDefaultMaxScreenBrightness = 4095;
+
+// Each step will stay on for 50ms by default.
+constexpr auto kRampStepDuration = 50;
+
+// Each value represents a duty percent (0 - 100) for the led pwm.
+constexpr std::array kBrightnessRamp = {0, 12, 25, 37, 50, 72, 85, 100};
+
+// Write value to path and close file.
+bool WriteToFile(const std::string& path, uint32_t content) {
+ return WriteStringToFile(std::to_string(content), path);
}
-static void set(std::string path, int value) {
- set(path, std::to_string(value));
+bool WriteToFile(const std::string& path, const std::string& content) {
+ return WriteStringToFile(content, path);
}
-static uint32_t getBrightness(const LightState& state) {
- uint32_t alpha, red, green, blue;
+uint32_t RgbaToBrightness(uint32_t color) {
+ // Extract brightness from AARRGGBB.
+ uint32_t alpha = (color >> 24) & 0xFF;
- /*
- * Extract brightness from AARRGGBB.
- */
- alpha = (state.color >> 24) & 0xFF;
- red = (state.color >> 16) & 0xFF;
- green = (state.color >> 8) & 0xFF;
- blue = state.color & 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 brightness if Alpha brightness is not 0xFF.
- */
+ // Scale RGB colors if a brightness has been applied by the user
if (alpha != 0xFF) {
red = red * alpha / 0xFF;
green = green * alpha / 0xFF;
@@ -97,130 +77,133 @@ static uint32_t getBrightness(const LightState& state) {
return (77 * red + 150 * green + 29 * blue) >> 8;
}
+inline uint32_t RgbaToBrightness(uint32_t color, uint32_t max_brightness) {
+ return RgbaToBrightness(color) * max_brightness / 0xFF;
+}
+
/*
* Scale each value of the brightness ramp according to the
* brightness of the color.
*/
-static std::string getScaledRamp(uint32_t brightness) {
- std::string ramp, pad;
+std::string GetScaledDutyPcts(uint32_t brightness) {
+ std::stringstream ramp;
- for (auto const& step : BRIGHTNESS_RAMP) {
- ramp += pad + std::to_string(step * brightness / 0xFF);
- pad = ",";
+ for (size_t i = 0; i < kBrightnessRamp.size(); i++) {
+ if (i > 0) ramp << ",";
+ ramp << kBrightnessRamp[i] * brightness / 0xFF;
}
- return ramp;
+ return ramp.str();
}
-static inline uint32_t scaleBrightness(uint32_t brightness, uint32_t maxBrightness) {
- return brightness * maxBrightness / 0xFF;
+inline bool IsLit(uint32_t color) {
+ return color & 0x00ffffff;
}
-static inline uint32_t getScaledBrightness(const LightState& state, uint32_t maxBrightness) {
- return scaleBrightness(getBrightness(state), maxBrightness);
-}
+} // anonymous namespace
-static void handleXiaomiBacklight(Type /*type*/, const LightState& state) {
- uint32_t brightness = getScaledBrightness(state, MAX_LCD_BRIGHTNESS);
- set(LCD_LED BRIGHTNESS, brightness);
-}
-
-static void setNotification(const LightState& state) {
- uint32_t whiteBrightness = getScaledBrightness(state, MAX_LED_BRIGHTNESS);
-
- /* Turn off the leds (initially) */
- set(WHITE 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;
+namespace android {
+namespace hardware {
+namespace light {
+namespace V2_0 {
+namespace implementation {
- if (pauseHi < 0) {
- pauseHi = 0;
- }
+Light::Light() {
+ std::string buf;
- /* White */
- set(WHITE START_IDX, 0 * RAMP_STEPS);
- set(WHITE DUTY_PCTS, getScaledRamp(whiteBrightness));
- set(WHITE PAUSE_LO, pauseLo);
- set(WHITE PAUSE_HI, pauseHi);
- set(WHITE RAMP_STEP_MS, stepDuration);
- set(WHITE BLINK, 1);
+ if (ReadFileToString(LCD_ATTR(max_brightness), &buf)) {
+ max_screen_brightness_ = std::stoi(buf);
} else {
- set(WHITE BRIGHTNESS, whiteBrightness);
+ max_screen_brightness_ = kDefaultMaxScreenBrightness;
+ LOG(ERROR) << "Failed to read max screen brightness, fallback to "
+ << kDefaultMaxLedBrightness;
}
-}
-
-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<std::pair<Type, LightState>> notificationStates = {
- { Type::ATTENTION, offState },
- { Type::NOTIFICATIONS, offState },
- { Type::BATTERY, offState },
-};
-
-static void handleXiaomiNotification(Type type, const LightState& state) {
- for(auto it : notificationStates) {
- if (it.first == type) {
- it.second = state;
- }
-
- if (isLit(it.second)) {
- setNotification(it.second);
- return;
- }
+ if (ReadFileToString(WHITE_ATTR(max_brightness), &buf)) {
+ max_led_brightness_ = std::stoi(buf);
+ } else {
+ max_led_brightness_ = kDefaultMaxLedBrightness;
+ LOG(ERROR) << "Failed to read max LED brightness, fallback to " << kDefaultMaxLedBrightness;
}
-
- setNotification(offState);
}
-static std::map<Type, std::function<void(Type type, const LightState&)>> lights = {
- {Type::BACKLIGHT, handleXiaomiBacklight},
- {Type::NOTIFICATIONS, handleXiaomiNotification},
- {Type::BATTERY, handleXiaomiNotification},
- {Type::ATTENTION, handleXiaomiNotification},
-};
-
-Light::Light() {}
-
Return<Status> Light::setLight(Type type, const LightState& state) {
- auto it = lights.find(type);
+ auto it = lights_.find(type);
- if (it == lights.end()) {
+ if (it == lights_.end()) {
return Status::LIGHT_NOT_SUPPORTED;
}
- /*
- * Lock global mutex until light state is updated.
- */
-
- std::lock_guard<std::mutex> lock(globalLock);
it->second(type, state);
+
return Status::SUCCESS;
}
Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb) {
std::vector<Type> types;
- for (auto const& light : lights) types.push_back(light.first);
+ for (auto&& light : lights_) types.emplace_back(light.first);
_hidl_cb(types);
return Void();
}
+void Light::setLightBacklight(Type /*type*/, const LightState& state) {
+ uint32_t brightness = RgbaToBrightness(state.color, max_screen_brightness_);
+ WriteToFile(LCD_ATTR(brightness), brightness);
+}
+
+void Light::setLightNotification(Type type, const LightState& state) {
+ bool found = false;
+ for (auto&& [cur_type, cur_state] : notif_states_) {
+ if (cur_type == type) {
+ cur_state = state;
+ }
+
+ // Fallback to battery light
+ if (!found && (cur_type == Type::BATTERY || IsLit(state.color))) {
+ found = true;
+ LOG(DEBUG) << __func__ << ": type=" << toString(cur_type);
+ applyNotificationState(state);
+ }
+ }
+}
+
+void Light::applyNotificationState(const LightState& state) {
+ uint32_t white_brightness = RgbaToBrightness(state.color, max_led_brightness_);
+
+ // Turn off the leds (initially)
+ WriteToFile(WHITE_ATTR(blink), 0);
+
+ if (state.flashMode == Flash::TIMED && state.flashOnMs > 0 && state.flashOffMs > 0) {
+ /*
+ * 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 step_duration = kRampStepDuration;
+ int32_t pause_hi = state.flashOnMs - (step_duration * kBrightnessRamp.size() * 2);
+ if (pause_hi < 0) {
+ step_duration = state.flashOnMs / (kBrightnessRamp.size() * 2);
+ pause_hi = 0;
+ }
+
+ LOG(DEBUG) << __func__ << ": color=" << std::hex << state.color << std::dec
+ << " onMs=" << state.flashOnMs << " offMs=" << state.flashOffMs;
+
+ // White
+ WriteToFile(WHITE_ATTR(start_idx), 0);
+ WriteToFile(WHITE_ATTR(duty_pcts), GetScaledDutyPcts(white_brightness));
+ WriteToFile(WHITE_ATTR(pause_lo), static_cast<uint32_t>(state.flashOffMs));
+ WriteToFile(WHITE_ATTR(pause_hi), static_cast<uint32_t>(pause_hi));
+ WriteToFile(WHITE_ATTR(ramp_step_ms), static_cast<uint32_t>(step_duration));
+ WriteToFile(WHITE_ATTR(blink), 1);
+ } else {
+ WriteToFile(WHITE_ATTR(brightness), white_brightness);
+ }
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace light