Add the support of lights HAL
Bug: 230288032 Test: atest VtsHalLightTargetTest Change-Id: I076e76f589a202833095b14a839500a26c35e9b3 Signed-off-by: Chungjui Fan <chungjuifan@google.com>
This commit is contained in:
parent
fdca91b2ac
commit
0d44479f24
6 changed files with 348 additions and 0 deletions
23
lights/Android.bp
Normal file
23
lights/Android.bp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package {
|
||||||
|
// See: http://go/android-license-faq
|
||||||
|
// A large-scale-change added 'default_applicable_licenses' to import
|
||||||
|
// all of the 'license_kinds' from "//device/google/tangorpro:device_google_tangorpro_license"
|
||||||
|
// to get the below license kinds:
|
||||||
|
// SPDX-license-identifier-Apache-2.0
|
||||||
|
default_applicable_licenses: ["//device/google/tangorpro:device_google_tangorpro_license"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_binary {
|
||||||
|
name: "android.hardware.lights-service.tangorpro",
|
||||||
|
relative_install_path: "hw",
|
||||||
|
init_rc: ["android.hardware.lights-service.tangorpro.rc"],
|
||||||
|
vintf_fragments: ["android.hardware.lights-service.tangorpro.xml"],
|
||||||
|
vendor: true,
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
"libbinder_ndk",
|
||||||
|
"android.hardware.light-V2-ndk",
|
||||||
|
],
|
||||||
|
|
||||||
|
srcs: ["Lights.cpp", "led_lut_calibrator.cpp"],
|
||||||
|
}
|
151
lights/Lights.cpp
Normal file
151
lights/Lights.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <aidl/android/hardware/light/BnLights.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android/binder_manager.h>
|
||||||
|
#include <android/binder_process.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "led_lut_calibrator.h"
|
||||||
|
|
||||||
|
using ::aidl::android::hardware::light::BnLights;
|
||||||
|
using ::aidl::android::hardware::light::HwLight;
|
||||||
|
using ::aidl::android::hardware::light::HwLightState;
|
||||||
|
using ::aidl::android::hardware::light::ILights;
|
||||||
|
using ::aidl::android::hardware::light::LightType;
|
||||||
|
using ::ndk::ScopedAStatus;
|
||||||
|
using ::ndk::SharedRefBase;
|
||||||
|
|
||||||
|
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
char const *const GREEN_LED_FILE = "/sys/class/leds/green/brightness";
|
||||||
|
|
||||||
|
enum { ARGB_ON_IN_DAY = 0x0000ff00, ARGB_ON_IN_NIGHT = 0x00008000, ARGB_OFF = 0x00000000 };
|
||||||
|
enum { DAY = 4095, NIGHT = 0 };
|
||||||
|
|
||||||
|
static int sys_write_int(int fd, int value) {
|
||||||
|
char buffer[16];
|
||||||
|
size_t bytes;
|
||||||
|
ssize_t amount;
|
||||||
|
|
||||||
|
bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
|
||||||
|
if (bytes >= sizeof(buffer)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
amount = write(fd, buffer, bytes);
|
||||||
|
|
||||||
|
return amount == -1 ? -errno : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Lights : public BnLights {
|
||||||
|
private:
|
||||||
|
std::vector<HwLight> availableLights;
|
||||||
|
LedLutCalibrator calibrator;
|
||||||
|
|
||||||
|
void addLight(LightType const type, int const ordinal) {
|
||||||
|
HwLight light{};
|
||||||
|
light.id = availableLights.size();
|
||||||
|
light.type = type;
|
||||||
|
light.ordinal = ordinal;
|
||||||
|
availableLights.emplace_back(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeLed(const char *path, int color) {
|
||||||
|
int fd = open(path, O_WRONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
LOG(ERROR) << "Failed to open LED device " << path << strerror(errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sys_write_int(fd, color);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Lights() : BnLights() {
|
||||||
|
pthread_mutex_init(&g_lock, NULL);
|
||||||
|
|
||||||
|
addLight(LightType::BACKLIGHT, 0);
|
||||||
|
addLight(LightType::KEYBOARD, 0);
|
||||||
|
addLight(LightType::BUTTONS, 0);
|
||||||
|
addLight(LightType::BATTERY, 0);
|
||||||
|
addLight(LightType::NOTIFICATIONS, 0);
|
||||||
|
addLight(LightType::ATTENTION, 0);
|
||||||
|
addLight(LightType::BLUETOOTH, 0);
|
||||||
|
addLight(LightType::WIFI, 0);
|
||||||
|
addLight(LightType::MICROPHONE, 0);
|
||||||
|
addLight(LightType::CAMERA, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedAStatus setLightState(int id, const HwLightState &state) override {
|
||||||
|
if (!(0 <= id && id < availableLights.size())) {
|
||||||
|
LOG(ERROR) << "Light id " << (int32_t)id << " does not exist.";
|
||||||
|
return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
HwLight const &light = availableLights[id];
|
||||||
|
int cal_color = 0;
|
||||||
|
switch (light.type) {
|
||||||
|
case LightType::CAMERA:
|
||||||
|
if (state.color == ARGB_ON_IN_DAY) {
|
||||||
|
cal_color = calibrator.GetByColorIntensity("green", DAY);
|
||||||
|
} else if (state.color == ARGB_ON_IN_NIGHT) {
|
||||||
|
cal_color = calibrator.GetByColorIntensity("green", NIGHT);
|
||||||
|
} else if (state.color == ARGB_OFF) {
|
||||||
|
cal_color = 0;
|
||||||
|
} else {
|
||||||
|
goto setLightState_end;
|
||||||
|
}
|
||||||
|
if (cal_color < 0) {
|
||||||
|
goto setLightState_end;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&g_lock);
|
||||||
|
writeLed(GREEN_LED_FILE, cal_color);
|
||||||
|
pthread_mutex_unlock(&g_lock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLightState_end:
|
||||||
|
return ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedAStatus getLights(std::vector<HwLight> *lights) override {
|
||||||
|
for (auto i = availableLights.begin(); i != availableLights.end(); i++) {
|
||||||
|
lights->push_back(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||||
|
|
||||||
|
std::shared_ptr<Lights> light = SharedRefBase::make<Lights>();
|
||||||
|
|
||||||
|
const std::string instance = std::string() + ILights::descriptor + "/default";
|
||||||
|
binder_status_t status = AServiceManager_addService(light->asBinder().get(), instance.c_str());
|
||||||
|
|
||||||
|
if (status != STATUS_OK) {
|
||||||
|
LOG(ERROR) << "Failed to register" << instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
ABinderProcess_joinThreadPool();
|
||||||
|
|
||||||
|
return -1; // should not reach
|
||||||
|
}
|
11
lights/android.hardware.lights-service.tangorpro.rc
Normal file
11
lights/android.hardware.lights-service.tangorpro.rc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
service vendor.lights-tangotron /vendor/bin/hw/android.hardware.lights-service.tangorpro
|
||||||
|
interface aidl android.hardware.light.ILights/default
|
||||||
|
class hal
|
||||||
|
user system
|
||||||
|
group system
|
||||||
|
# shutting off lights while powering-off
|
||||||
|
shutdown critical
|
||||||
|
|
||||||
|
on post-fs
|
||||||
|
chown system system /sys/class/leds/green/brightness
|
||||||
|
chmod 664 /sys/class/leds/green/brightness
|
7
lights/android.hardware.lights-service.tangorpro.xml
Normal file
7
lights/android.hardware.lights-service.tangorpro.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<manifest version="1.0" type="device">
|
||||||
|
<hal format="aidl">
|
||||||
|
<name>android.hardware.light</name>
|
||||||
|
<fqname>ILights/default</fqname>
|
||||||
|
<version>2</version>
|
||||||
|
</hal>
|
||||||
|
</manifest>
|
117
lights/led_lut_calibrator.cpp
Normal file
117
lights/led_lut_calibrator.cpp
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "led_lut_calibrator.h"
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
const char kCalibrationPath[] = "/mnt/vendor/persist/led/led_calibration_LUT.txt";
|
||||||
|
|
||||||
|
LedLutCalibrator::LedLutCalibrator() {
|
||||||
|
if (!ReadCalibrationTable()) {
|
||||||
|
LOG(ERROR) << "Failed to read calibration table";
|
||||||
|
cal_table_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LedLutCalibrator::GetByColorIntensity(const std::string &color, int intensity) const {
|
||||||
|
std::string key = MakeLutKey(color, intensity);
|
||||||
|
const auto cal_data = cal_table_.find(key);
|
||||||
|
|
||||||
|
if (cal_data == cal_table_.end()) {
|
||||||
|
LOG(ERROR) << "Failed to get calibration data";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cal_data->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LedLutCalibrator::ReadCalibrationTable() {
|
||||||
|
int fd;
|
||||||
|
int bytes;
|
||||||
|
bool ret = true;
|
||||||
|
std::vector<uint8_t> buffer;
|
||||||
|
buffer.resize(512);
|
||||||
|
|
||||||
|
fd = open(kCalibrationPath, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
LOG(ERROR) << "Failed to open " << kCalibrationPath;
|
||||||
|
ret = false;
|
||||||
|
goto ReadCalibrationTable_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = read(fd, buffer.data(), buffer.size());
|
||||||
|
if (bytes == -1) {
|
||||||
|
LOG(ERROR) << "Failed to read " << kCalibrationPath;
|
||||||
|
ret = false;
|
||||||
|
goto ReadCalibrationTable_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParseBlock(&buffer)) {
|
||||||
|
LOG(ERROR) << "Failed to parse calibration table ";
|
||||||
|
ret = false;
|
||||||
|
goto ReadCalibrationTable_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadCalibrationTable_err:
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LedLutCalibrator::ParseBlock(const std::vector<uint8_t> *table) {
|
||||||
|
std::string str(table->begin(), table->end());
|
||||||
|
auto result = std::vector<std::string>{};
|
||||||
|
auto ss = std::stringstream{str};
|
||||||
|
|
||||||
|
for (std::string line; std::getline(ss, line, '\n');) {
|
||||||
|
size_t start;
|
||||||
|
size_t end = 0;
|
||||||
|
std::vector<std::string> colon_separated;
|
||||||
|
while ((start = line.find_first_not_of(':', end)) != std::string::npos) {
|
||||||
|
end = line.find(':', start);
|
||||||
|
if (end == std::string::npos) {
|
||||||
|
end = line.size();
|
||||||
|
}
|
||||||
|
colon_separated.push_back(line.substr(start, end - start));
|
||||||
|
}
|
||||||
|
if (colon_separated.size() != 3) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string color_name = colon_separated[0];
|
||||||
|
uint16_t intensity = atoi(colon_separated[1].c_str());
|
||||||
|
uint16_t pwm = atoi(colon_separated[2].c_str());
|
||||||
|
std::cout << color_name << intensity << pwm << std::endl;
|
||||||
|
std::string key = MakeLutKey(color_name, intensity);
|
||||||
|
cal_table_[key] = pwm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LedLutCalibrator::MakeLutKey(const std::string &color, int intensity) const {
|
||||||
|
std::string intensity_str = std::to_string(intensity);
|
||||||
|
std::string terms{color};
|
||||||
|
|
||||||
|
terms.append(intensity_str);
|
||||||
|
|
||||||
|
return terms;
|
||||||
|
}
|
39
lights/led_lut_calibrator.h
Normal file
39
lights/led_lut_calibrator.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GOOGLE_TANGOTRON_LIGHTS_LED_LUT_CALIBRATOR_H_
|
||||||
|
#define GOOGLE_TANGOTRON_LIGHTS_LED_LUT_CALIBRATOR_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class LedLutCalibrator {
|
||||||
|
public:
|
||||||
|
LedLutCalibrator();
|
||||||
|
LedLutCalibrator &operator=(const LedLutCalibrator &) = delete;
|
||||||
|
~LedLutCalibrator() = default;
|
||||||
|
int GetByColorIntensity(const std::string &color, int intensity) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ReadCalibrationTable();
|
||||||
|
bool ParseBlock(const std::vector<uint8_t> *table);
|
||||||
|
std::string MakeLutKey(const std::string &color, int intensity) const;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, int> cal_table_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GOOGLE_TANGOTRON_LIGHTS_LED_LUT_CALIBRATOR_H_
|
Loading…
Add table
Add a link
Reference in a new issue