Commit dceb61a3 authored by TARKZiM's avatar TARKZiM Committed by Bernhard Thoben
Browse files

kitakami-common: light: Switch back to classic HAL

* Trying to fix notification led blinking, will re-write
  our HIDL HAL in the future.

* Move led permissions to on init before HIDL service starts.
parent 36623406
......@@ -214,7 +214,9 @@ PRODUCT_PACKAGES += \
# Lights
PRODUCT_PACKAGES += \
android.hardware.light@2.0-service.kitakami
android.hardware.light@2.0-service \
android.hardware.light@2.0-impl \
lights.msm8994
# LiveDisplay
PRODUCT_PACKAGES += \
......
//
// 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.
cc_binary {
name: "android.hardware.light@2.0-service.kitakami",
relative_install_path: "hw",
init_rc: ["android.hardware.light@2.0-service.kitakami.rc"],
srcs: ["service.cpp", "Light.cpp"],
shared_libs: [
"libbase",
"libcutils",
"libhardware",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libutils",
"android.hardware.light@2.0",
],
proprietary: true,
}
# Copyright (C) 2008 The Android Open Source 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.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
ifeq ($(TARGET_HAS_LOW_PERSISTENCE_DISPLAY),true)
LOCAL_CFLAGS += -DLOW_PERSISTENCE_DISPLAY
endif
ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
LOCAL_SRC_FILES := lights.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_VENDOR_MODULE := true
include $(BUILD_SHARED_LIBRARY)
/*
* 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::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)
: mLcdBacklight(std::move(lcd_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)) {
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 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::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::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;
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;
} 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
/*
* 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 <android/hardware/light/2.0/ILight.h>
#include <hidl/Status.h>
#include <fstream>
#include <mutex>
#include <unordered_map>
namespace android {
namespace hardware {
namespace light {
namespace V2_0 {
namespace implementation {
struct Light : public ILight {
Light(std::pair<std::ofstream, uint32_t>&& lcd_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);
// Methods from ::android::hardware::light::V2_0::ILight follow.
Return<Status> setLight(Type type, const LightState& state) override;
Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb) override;
private:
void setAttentionLight(const LightState& state);
void setBatteryLight(const LightState& state);
void setLcdBacklight(const LightState& state);
void setNotificationLight(const LightState& state);
void setSpeakerBatteryLightLocked();
void setSpeakerLightLocked(const LightState& state);
std::pair<std::ofstream, uint32_t> mLcdBacklight;
std::ofstream mRedLed;
std::ofstream mGreenLed;
std::ofstream mBlueLed;
std::ofstream mRedDutyPcts;
std::ofstream mGreenDutyPcts;
std::ofstream mBlueDutyPcts;
std::ofstream mRedStartIdx;
std::ofstream mGreenStartIdx;
std::ofstream mBlueStartIdx;
std::ofstream mRedPauseLo;
std::ofstream mGreenPauseLo;
std::ofstream mBluePauseLo;
std::ofstream mRedPauseHi;
std::ofstream mGreenPauseHi;
std::ofstream mBluePauseHi;
std::ofstream mRedRampStepMs;
std::ofstream mGreenRampStepMs;
std::ofstream mBlueRampStepMs;
std::ofstream mRedBlink;
std::ofstream mGreenBlink;
std::ofstream mBlueBlink;
LightState mAttentionState;
LightState mBatteryState;
LightState mNotificationState;
std::unordered_map<Type, std::function<void(const LightState&)>> mLights;
std::mutex mLock;
};
} // namespace implementation
} // namespace V2_0
} // namespace light
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
on init
# RGB lights
chown system system /sys/class/leds/red/pause_lo
chown system system /sys/class/leds/green/pause_lo
chown system system /sys/class/leds/blue/pause_lo
chown system system /sys/class/leds/red/pause_hi
chown system system /sys/class/leds/green/pause_hi
chown system system /sys/class/leds/blue/pause_hi
chown system system /sys/class/leds/red/blink
chown system system /sys/class/leds/green/blink
chown system system /sys/class/leds/blue/blink
chown system system /sys/class/leds/red/ramp_step_ms
chown system system /sys/class/leds/green/ramp_step_ms
chown system system /sys/class/leds/blue/ramp_step_ms
chown system system /sys/class/leds/red/duty_pcts
chown system system /sys/class/leds/green/duty_pcts
chown system system /sys/class/leds/blue/duty_pcts
chown system system /sys/class/leds/red/start_idx
chown system system /sys/class/leds/green/start_idx
chown system system /sys/class/leds/blue/start_idx
chmod 660 /sys/class/leds/red/ramp_step_ms
chmod 660 /sys/class/leds/green/ramp_step_ms
chmod 660 /sys/class/leds/blue/ramp_step_ms
chmod 660 /sys/class/leds/red/duty_pcts
chmod 660 /sys/class/leds/green/duty_pcts
chmod 660 /sys/class/leds/blue/duty_pcts
chmod 660 /sys/class/leds/red/start_idx
chmod 660 /sys/class/leds/green/start_idx
chmod 660 /sys/class/leds/blue/start_idx
service vendor.light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service.kitakami
class hal
user system
group system
# shutting off lights while powering-off
shutdown critical
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 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 "lights"
#include <cutils/log.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <hardware/lights.h>
/******************************************************************************/
static pthread_once_t g_init = PTHREAD_ONCE_INIT;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
static struct light_state_t g_attention;
static struct light_state_t g_notification;
static struct light_state_t g_battery;
static short backlight_bits = 8;
char const*const RED_LED_FILE
= "/sys/class/leds/red/brightness";
char const*const GREEN_LED_FILE
= "/sys/class/leds/green/brightness";
char const*const BLUE_LED_FILE
= "/sys/class/leds/blue/brightness";
char const*const LCD_FILE
= "/sys/class/leds/lcd-backlight/brightness";
char const*const LCD_MAX_FILE
= "/sys/class/leds/lcd-backlight/max_brightness";
char const*const RED_DUTY_PCTS_FILE
= "/sys/class/leds/red/duty_pcts";
char const*const GREEN_DUTY_PCTS_FILE
= "/sys/class/leds/green/duty_pcts";
char const*const BLUE_DUTY_PCTS_FILE
= "/sys/class/leds/blue/duty_pcts";
char const*const RED_START_IDX_FILE
= "/sys/class/leds/red/start_idx";
char const*const GREEN_START_IDX_FILE
= "/sys/class/leds/green/start_idx";
char const*const BLUE_START_IDX_FILE
= "/sys/class/leds/blue/start_idx";
char const*const RED_PAUSE_LO_FILE
= "/sys/class/leds/red/pause_lo";
char const*const GREEN_PAUSE_LO_FILE
= "/sys/class/leds/green/pause_lo";
char const*const BLUE_PAUSE_LO_FILE
= "/sys/class/leds/blue/pause_lo";
char const*const RED_PAUSE_HI_FILE
= "/sys/class/leds/red/pause_hi";
char const*const GREEN_PAUSE_HI_FILE
= "/sys/class/leds/green/pause_hi";
char const*const BLUE_PAUSE_HI_FILE
= "/sys/class/leds/blue/pause_hi";
char const*const RED_RAMP_STEP_MS_FILE
= "/sys/class/leds/red/ramp_step_ms";
char const*const GREEN_RAMP_STEP_MS_FILE
= "/sys/class/leds/green/ramp_step_ms";
char const*const BLUE_RAMP_STEP_MS_FILE
= "/sys/class/leds/blue/ramp_step_ms";
char const*const RED_BLINK_FILE
= "/sys/class/leds/red/blink";
char const*const GREEN_BLINK_FILE
= "/sys/class/leds/green/blink";
char const*const BLUE_BLINK_FILE
= "/sys/class/leds/blue/blink";
#define RAMP_SIZE 8
static int BRIGHTNESS_RAMP[RAMP_SIZE]
= { 0, 12, 25, 37, 50, 72, 85, 100 };
#define RAMP_STEP_DURATION 50
/**
* device methods
*/
static int
read_int(char const* path)
{
static int already_warned = 0;
int fd;
fd = open(path, O_RDONLY);
if (fd >= 0) {
char read_str[10] = {0,0,0,0,0,0,0,0,0,0};
ssize_t err = read(fd, &read_str, sizeof(read_str));
close(fd);
return err < 2 ? -errno : atoi(read_str);