aboutsummaryrefslogtreecommitdiff
path: root/light/Light.cpp
diff options
context:
space:
mode:
authorBruno Martins <bgcngm@gmail.com>2018-01-19 15:42:00 +0000
committerDavide Garberi <dade.garberi@gmail.com>2018-01-25 17:06:44 +0100
commite03f3220a3bb949ca5c11b78de3c6ce5228b0d19 (patch)
tree69e5478269bda2d50354ce8c6f821c37e5075833 /light/Light.cpp
parent01a7a3c04cde89a3ba8c81d55c3d29d9309ae8b5 (diff)
msm8996-common: Convert lights HAL into a native binderized HAL
Change-Id: If41458e22b9a67a5c2a415571723917df1904aa1 Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'light/Light.cpp')
-rw-r--r--light/Light.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/light/Light.cpp b/light/Light.cpp
new file mode 100644
index 0000000..a364f05
--- /dev/null
+++ b/light/Light.cpp
@@ -0,0 +1,295 @@
+/*
+ * 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 "LightService"
+
+#include "Light.h"
+
+#include <android-base/logging.h>
+
+namespace {
+using android::hardware::light::V2_0::LightState;
+
+static constexpr int RAMP_SIZE = 8;
+static constexpr int RAMP_STEP_DURATION = 50;
+
+static constexpr int BRIGHTNESS_RAMP[RAMP_SIZE] = {0, 12, 25, 37, 50, 72, 85, 100};
+static constexpr int DEFAULT_MAX_BRIGHTNESS = 255;
+
+static uint32_t rgbToBrightness(const LightState& state) {
+ uint32_t color = state.color & 0x00ffffff;
+ return ((77 * ((color >> 16) & 0xff)) + (150 * ((color >> 8) & 0xff)) +
+ (29 * (color & 0xff))) >> 8;
+}
+
+static bool isLit(const LightState& state) {
+ return (state.color & 0x00ffffff);
+}
+
+static std::string getScaledDutyPcts(int brightness) {
+ std::string buf, pad;
+
+ for (auto i : BRIGHTNESS_RAMP) {
+ buf += pad;
+ buf += std::to_string(i * brightness / 255);
+ pad = ",";
+ }
+
+ return buf;
+}
+} // anonymous namespace
+
+namespace android {
+namespace hardware {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+Light::Light(std::pair<std::ofstream, uint32_t>&& lcd_backlight,
+ std::vector<std::ofstream>&& button_backlight,
+ std::ofstream&& red_led, std::ofstream&& green_led, std::ofstream&& blue_led,
+ std::ofstream&& red_duty_pcts, std::ofstream&& green_duty_pcts, std::ofstream&& blue_duty_pcts,
+ std::ofstream&& red_start_idx, std::ofstream&& green_start_idx, std::ofstream&& blue_start_idx,
+ std::ofstream&& red_pause_lo, std::ofstream&& green_pause_lo, std::ofstream&& blue_pause_lo,
+ std::ofstream&& red_pause_hi, std::ofstream&& green_pause_hi, std::ofstream&& blue_pause_hi,
+ std::ofstream&& red_ramp_step_ms, std::ofstream&& green_ramp_step_ms, std::ofstream&& blue_ramp_step_ms,
+ std::ofstream&& red_blink, std::ofstream&& green_blink, std::ofstream&& blue_blink,
+ std::ofstream&& rgb_blink)
+ : mLcdBacklight(std::move(lcd_backlight)),
+ mButtonBacklight(std::move(button_backlight)),
+ mRedLed(std::move(red_led)),
+ mGreenLed(std::move(green_led)),
+ mBlueLed(std::move(blue_led)),
+ mRedDutyPcts(std::move(red_duty_pcts)),
+ mGreenDutyPcts(std::move(green_duty_pcts)),
+ mBlueDutyPcts(std::move(blue_duty_pcts)),
+ mRedStartIdx(std::move(red_start_idx)),
+ mGreenStartIdx(std::move(green_start_idx)),
+ mBlueStartIdx(std::move(blue_start_idx)),
+ mRedPauseLo(std::move(red_pause_lo)),
+ mGreenPauseLo(std::move(green_pause_lo)),
+ mBluePauseLo(std::move(blue_pause_lo)),
+ mRedPauseHi(std::move(red_pause_hi)),
+ mGreenPauseHi(std::move(green_pause_hi)),
+ mBluePauseHi(std::move(blue_pause_hi)),
+ mRedRampStepMs(std::move(red_ramp_step_ms)),
+ mGreenRampStepMs(std::move(green_ramp_step_ms)),
+ mBlueRampStepMs(std::move(blue_ramp_step_ms)),
+ mRedBlink(std::move(red_blink)),
+ mGreenBlink(std::move(green_blink)),
+ mBlueBlink(std::move(blue_blink)),
+ mRgbBlink(std::move(rgb_blink)) {
+ auto attnFn(std::bind(&Light::setAttentionLight, this, std::placeholders::_1));
+ auto backlightFn(std::bind(&Light::setLcdBacklight, this, std::placeholders::_1));
+ auto batteryFn(std::bind(&Light::setBatteryLight, this, std::placeholders::_1));
+ auto buttonsFn(std::bind(&Light::setButtonsBacklight, this, std::placeholders::_1));
+ auto notifFn(std::bind(&Light::setNotificationLight, this, std::placeholders::_1));
+ mLights.emplace(std::make_pair(Type::ATTENTION, attnFn));
+ mLights.emplace(std::make_pair(Type::BACKLIGHT, backlightFn));
+ mLights.emplace(std::make_pair(Type::BATTERY, batteryFn));
+ mLights.emplace(std::make_pair(Type::BUTTONS, buttonsFn));
+ mLights.emplace(std::make_pair(Type::NOTIFICATIONS, notifFn));
+}
+
+// Methods from ::android::hardware::light::V2_0::ILight follow.
+Return<Status> Light::setLight(Type type, const LightState& state) {
+ auto it = mLights.find(type);
+
+ if (it == mLights.end()) {
+ return Status::LIGHT_NOT_SUPPORTED;
+ }
+
+ it->second(state);
+
+ return Status::SUCCESS;
+}
+
+Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb) {
+ std::vector<Type> types;
+
+ for (auto const& light : mLights) {
+ types.push_back(light.first);
+ }
+
+ _hidl_cb(types);
+
+ return Void();
+}
+
+void Light::setAttentionLight(const LightState& state) {
+ std::lock_guard<std::mutex> lock(mLock);
+ mAttentionState = state;
+ setSpeakerBatteryLightLocked();
+}
+
+void Light::setLcdBacklight(const LightState& state) {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ uint32_t brightness = rgbToBrightness(state);
+
+ // If max panel brightness is not the default (255),
+ // apply linear scaling across the accepted range.
+ if (mLcdBacklight.second != DEFAULT_MAX_BRIGHTNESS) {
+ int old_brightness = brightness;
+ brightness = brightness * mLcdBacklight.second / DEFAULT_MAX_BRIGHTNESS;
+ LOG(VERBOSE) << "scaling brightness " << old_brightness << " => " << brightness;
+ }
+
+ mLcdBacklight.first << brightness << std::endl;
+}
+
+void Light::setButtonsBacklight(const LightState& state) {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ uint32_t brightness = rgbToBrightness(state);
+
+ for (auto& button : mButtonBacklight) {
+ button << brightness << std::endl;
+ }
+}
+
+void Light::setBatteryLight(const LightState& state) {
+ std::lock_guard<std::mutex> lock(mLock);
+ mBatteryState = state;
+ setSpeakerBatteryLightLocked();
+}
+
+void Light::setNotificationLight(const LightState& state) {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ uint32_t brightness, color, rgb[3];
+ LightState localState = state;
+
+ // If a brightness has been applied by the user
+ brightness = (localState.color & 0xff000000) >> 24;
+ if (brightness > 0 && brightness < 255) {
+ // Retrieve each of the RGB colors
+ color = localState.color & 0x00ffffff;
+ rgb[0] = (color >> 16) & 0xff;
+ rgb[1] = (color >> 8) & 0xff;
+ rgb[2] = color & 0xff;
+
+ // Apply the brightness level
+ if (rgb[0] > 0) {
+ rgb[0] = (rgb[0] * brightness) / 0xff;
+ }
+ if (rgb[1] > 0) {
+ rgb[1] = (rgb[1] * brightness) / 0xff;
+ }
+ if (rgb[2] > 0) {
+ rgb[2] = (rgb[2] * brightness) / 0xff;
+ }
+
+ // Update with the new color
+ localState.color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
+ }
+
+ mNotificationState = localState;
+ setSpeakerBatteryLightLocked();
+}
+
+void Light::setSpeakerBatteryLightLocked() {
+ if (isLit(mNotificationState)) {
+ setSpeakerLightLocked(mNotificationState);
+ } else if (isLit(mAttentionState)) {
+ setSpeakerLightLocked(mAttentionState);
+ } else if (isLit(mBatteryState)) {
+ setSpeakerLightLocked(mBatteryState);
+ } else {
+ // Lights off
+ mRedLed << 0 << std::endl;
+ mGreenLed << 0 << std::endl;
+ mBlueLed << 0 << std::endl;
+ mRedBlink << 0 << std::endl;
+ mGreenBlink << 0 << std::endl;
+ mBlueBlink << 0 << std::endl;
+ }
+}
+
+void Light::setSpeakerLightLocked(const LightState& state) {
+ int red, green, blue, blink;
+ int onMs, offMs, stepDuration, pauseHi;
+ uint32_t colorRGB = state.color;
+
+ switch (state.flashMode) {
+ case Flash::TIMED:
+ onMs = state.flashOnMs;
+ offMs = state.flashOffMs;
+ break;
+ case Flash::NONE:
+ default:
+ onMs = 0;
+ offMs = 0;
+ break;
+ }
+
+ red = (colorRGB >> 16) & 0xff;
+ green = (colorRGB >> 8) & 0xff;
+ blue = colorRGB & 0xff;
+ blink = onMs > 0 && offMs > 0;
+
+ // Disable all blinking to start
+ mRgbBlink << 0 << std::endl;
+
+ if (blink) {
+ stepDuration = RAMP_STEP_DURATION;
+ pauseHi = onMs - (stepDuration * RAMP_SIZE * 2);
+
+ if (stepDuration * RAMP_SIZE * 2 > onMs) {
+ stepDuration = onMs / (RAMP_SIZE * 2);
+ pauseHi = 0;
+ }
+
+ // Red
+ mRedStartIdx << 0 << std::endl;
+ mRedDutyPcts << getScaledDutyPcts(red) << std::endl;
+ mRedPauseLo << offMs << std::endl;
+ mRedPauseHi << pauseHi << std::endl;
+ mRedRampStepMs << stepDuration << std::endl;
+
+ // Green
+ mGreenStartIdx << RAMP_SIZE << std::endl;
+ mGreenDutyPcts << getScaledDutyPcts(green) << std::endl;
+ mGreenPauseLo << offMs << std::endl;
+ mGreenPauseHi << pauseHi << std::endl;
+ mGreenRampStepMs << stepDuration << std::endl;
+
+ // Blue
+ mBlueStartIdx << RAMP_SIZE * 2 << std::endl;
+ mBlueDutyPcts << getScaledDutyPcts(blue) << std::endl;
+ mBluePauseLo << offMs << std::endl;
+ mBluePauseHi << pauseHi << std::endl;
+ mBlueRampStepMs << stepDuration << std::endl;
+
+ // Start the party
+ mRgbBlink << 1 << std::endl;
+ } else {
+ if (red == 0 && green == 0 && blue == 0) {
+ mRedBlink << 0 << std::endl;
+ mGreenBlink << 0 << std::endl;
+ mBlueBlink << 0 << std::endl;
+ }
+ mRedLed << red << std::endl;
+ mGreenLed << green << std::endl;
+ mBlueLed << blue << std::endl;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace light
+} // namespace hardware
+} // namespace android