diff --git a/light/Light.cpp b/light/Light.cpp index 9fd5c9f..c630e50 100644 --- a/light/Light.cpp +++ b/light/Light.cpp @@ -1,109 +1,223 @@ -/* - * 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 "LightsService" - -#include "Light.h" - -#include -#include -#include - -namespace android { -namespace hardware { -namespace light { -namespace V2_0 { -namespace implementation { - -/* - * Write value to path and close file. - */ -template -static void set(const std::string& path, const T& value) { - std::ofstream file(path); - file << value; -} - -/* - * Read from path and close file. - * Return def in case of any failure. - */ -template -static T get(const std::string& path, const T& def) { - std::ifstream file(path); - T result; - - file >> result; - return file.fail() ? def : result; -} - -static constexpr int kDefaultMaxBrightness = 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; -} - -Light::Light() { - mLights.emplace(Type::BACKLIGHT, std::bind(&Light::handleBacklight, this, std::placeholders::_1)); -} - -void Light::handleBacklight(const LightState& state) { - int maxBrightness = get("/sys/class/backlight/panel0-backlight/max_brightness", -1); - if (maxBrightness < 0) { - maxBrightness = kDefaultMaxBrightness; - } - uint32_t sentBrightness = rgbToBrightness(state); - uint32_t brightness = sentBrightness * maxBrightness / kDefaultMaxBrightness; - LOG(DEBUG) << "Writing backlight brightness " << brightness - << " (orig " << sentBrightness << ")"; - set("/sys/class/backlight/panel0-backlight/brightness", brightness); -} - -Return Light::setLight(Type type, const LightState& state) { - auto it = mLights.find(type); - - if (it == mLights.end()) { - return Status::LIGHT_NOT_SUPPORTED; - } - - // Lock global mutex until light state is updated. - std::lock_guard lock(mLock); - - it->second(state); - - return Status::SUCCESS; -} - -Return Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb) { - std::vector types; - - for (auto const& light : mLights) { - types.push_back(light.first); - } - - _hidl_cb(types); - - return Void(); -} - -} // namespace implementation -} // namespace V2_0 -} // namespace light -} // namespace hardware -} // namespace android +/* + * 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 RED_LED "/sys/class/leds/red/" +#define BLUE_LED "/sys/class/leds/blue/" +#define GREEN_LED "/sys/class/leds/green/" + +#define BREATH "breath" +#define BRIGHTNESS "brightness" +#define MAX_BRIGHTNESS "max_brightness" +#define DELAY_OFF "delay_off" +#define DELAY_ON "delay_on" + +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 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); +} + +static void handleNotification(const LightState& state) { + uint32_t redBrightness = scaleBrightness( (state.color >> 16) & 0xFF, getMaxBrightness(RED_LED MAX_BRIGHTNESS)); + uint32_t blueBrightness = scaleBrightness( state.color & 0xFF, getMaxBrightness(BLUE_LED MAX_BRIGHTNESS)); + uint32_t greenBrightness = scaleBrightness((state.color >> 8) & 0xFF, getMaxBrightness(GREEN_LED MAX_BRIGHTNESS)); + + /* Disable breathing or blinking */ + set(RED_LED BREATH, 0); + set(RED_LED DELAY_OFF, 0); + set(RED_LED DELAY_ON, 0); + + set(BLUE_LED BREATH, 0); + set(BLUE_LED DELAY_OFF, 0); + set(BLUE_LED DELAY_ON, 0); + + set(GREEN_LED BREATH, 0); + set(GREEN_LED DELAY_OFF, 0); + set(GREEN_LED DELAY_ON, 0); + + switch (state.flashMode) { + case Flash::HARDWARE: + /* Breathing */ + set(RED_LED BREATH, 1); + set(BLUE_LED BREATH, 1); + set(GREEN_LED BREATH, 1); + break; + case Flash::TIMED: + /* Blinking */ + set(RED_LED DELAY_OFF, state.flashOnMs); + set(RED_LED DELAY_ON, state.flashOffMs); + set(BLUE_LED DELAY_OFF, state.flashOnMs); + set(BLUE_LED DELAY_ON, state.flashOffMs); + set(GREEN_LED DELAY_OFF, state.flashOnMs); + set(GREEN_LED DELAY_ON, state.flashOffMs); + break; + case Flash::NONE: + default: + break; + } + set(RED_LED BRIGHTNESS, redBrightness); + set(BLUE_LED BRIGHTNESS, blueBrightness); + set(GREEN_LED BRIGHTNESS, greenBrightness); + +} + +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 index 53d774b..4f102d8 100644 --- a/light/Light.h +++ b/light/Light.h @@ -1,60 +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 - -namespace android { -namespace hardware { -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(); - - Return setLight(Type type, const LightState& state) override; - Return getSupportedTypes(getSupportedTypes_cb _hidl_cb) override; - - private: - void handleBacklight(const LightState& state); - - std::mutex mLock; - std::unordered_map> mLights; -}; - -} // namespace implementation -} // namespace V2_0 -} // namespace light -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H +/* + * 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.lenovo_kunlun2.rc b/light/android.hardware.light@2.0-service.lenovo_kunlun2.rc index b54ca95..b69e27b 100644 --- a/light/android.hardware.light@2.0-service.lenovo_kunlun2.rc +++ b/light/android.hardware.light@2.0-service.lenovo_kunlun2.rc @@ -1,3 +1,34 @@ +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/red/breath + chown system system /sys/class/leds/red/brightness + chown system system /sys/class/leds/red/delay_on + chown system system /sys/class/leds/red/delay_off + chown system system /sys/class/leds/green/breath + chown system system /sys/class/leds/green/brightness + chown system system /sys/class/leds/green/delay_on + chown system system /sys/class/leds/green/delay_off + chown system system /sys/class/leds/blue/breath + chown system system /sys/class/leds/blue/brightness + chown system system /sys/class/leds/blue/delay_on + chown system system /sys/class/leds/blue/delay_off + + chmod 0644 /sys/class/backlight/panel0-backlight/brightness + chmod 0644 /sys/class/backlight/panel0-backlight/max_brightness + chmod 0644 /sys/class/leds/red/breath + chmod 0644 /sys/class/leds/red/brightness + chmod 0644 /sys/class/leds/red/delay_on + chmod 0644 /sys/class/leds/red/delay_off + chmod 0644 /sys/class/leds/green/breath + chmod 0644 /sys/class/leds/green/brightness + chmod 0644 /sys/class/leds/green/delay_on + chmod 0644 /sys/class/leds/green/delay_off + chmod 0644 /sys/class/leds/blue/breath + chmod 0644 /sys/class/leds/blue/brightness + chmod 0644 /sys/class/leds/blue/delay_on + chmod 0644 /sys/class/leds/blue/delay_off + service vendor.light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service interface android.hardware.light@2.0::ILight default class hal diff --git a/light/service.cpp b/light/service.cpp index 0725b75..c07290e 100644 --- a/light/service.cpp +++ b/light/service.cpp @@ -1,62 +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.lenovo_kunlun2" - -#include -#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() { - status_t status; - sp service = nullptr; - - LOG(INFO) << "Light HAL service 2.0 is starting."; - - service = new Light(); - if (service == nullptr) { - LOG(ERROR) << "Can not create an instance of Light HAL Iface, exiting."; - goto shutdown; - } - - configureRpcThreadpool(1, true /*callerWillJoin*/); - - status = service->registerAsService(); - if (status != OK) { - LOG(ERROR) << "Could not register service for Light HAL Iface (" << status << ")"; - goto shutdown; - } - - LOG(INFO) << "Light HAL service is ready."; - joinRpcThreadpool(); - // Should not pass this line - -shutdown: - // In normal operation, we don't expect the thread pool to exit - LOG(ERROR) << "Light HAL service is shutting down."; - return 1; -} +/* + * 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.lenovo_kunlun2" + +#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/overlay-pe/frameworks/base/core/res/res/values/custom_config.xml b/overlay-pe/frameworks/base/core/res/res/values/custom_config.xml index 1647c0f..eeb5567 100644 --- a/overlay-pe/frameworks/base/core/res/res/values/custom_config.xml +++ b/overlay-pe/frameworks/base/core/res/res/values/custom_config.xml @@ -15,6 +15,40 @@ for different hardware and product builds. Do not translate. --> + + 75 + true