diff --git a/src/ledflasher/ledflasher.cpp b/src/ledflasher/ledflasher.cpp index 3c5fed18f94da74716016720e8658e537aa17326..4d43df240b413a7cb8d96dfcdda20e68e6f16237 100644 --- a/src/ledflasher/ledflasher.cpp +++ b/src/ledflasher/ledflasher.cpp @@ -189,7 +189,9 @@ void Daemon::UpdateDeviceState() { {"_ledflasher._status", status_}, {"_ledflasher._leds", leds}, }; - CHECK(device_->SetStateProperties(state_change, nullptr)); + // TODO: Come up with a design for ledflasher.cpp such that this call never + // fails. + device_->SetStateProperties(state_change, nullptr); } int main(int argc, char* argv[]) { diff --git a/src/ledservice/Android.mk b/src/ledservice/Android.mk index e7392320f4a9c5b7dde4f071d8dc25c28e4730ea..492211ca60fa1c0124b341e2b10fe518f9bd2d82 100644 --- a/src/ledservice/Android.mk +++ b/src/ledservice/Android.mk @@ -32,9 +32,11 @@ LOCAL_SHARED_LIBRARIES := \ libchrome \ libchrome-dbus \ libdbus \ + libhardware \ + libutils \ LOCAL_C_INCLUDES := external/gtest/include -LOCAL_CFLAGS := -Wall -Werror -Wno-sign-promo +LOCAL_CFLAGS := -Wall -Werror -Wno-sign-promo -Wno-missing-field-initializers LOCAL_RTTI_FLAG := -frtti include $(BUILD_EXECUTABLE) diff --git a/src/ledservice/ledstatus.cpp b/src/ledservice/ledstatus.cpp index 5fac42cd62636d13e71dd4a4680f9b9ad6815074..a51ea2ac2979d0686c22ab16b92c5ef419b7f945 100644 --- a/src/ledservice/ledstatus.cpp +++ b/src/ledservice/ledstatus.cpp @@ -47,7 +47,61 @@ brillo::StreamPtr GetLEDDataStream(size_t index, bool write) { } // anonymous namespace +LedStatus::LedStatus() { + // Try to open the lights hal. + int ret = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, &lights_hal_); + if (ret) { + LOG(ERROR) << "Failed to load the lights HAL."; + return; + } + CHECK(lights_hal_); + LOG(INFO) << "Loaded lights HAL."; + + // If we can open the hal, then we map each number from 1 - 4 to one of the + // leds available on the board. Note, multiple numbers could be mapped to the + // same led. + const std::initializer_list<const char*> kLogicalLights = { + LIGHT_ID_BACKLIGHT, LIGHT_ID_KEYBOARD, LIGHT_ID_BUTTONS, LIGHT_ID_BATTERY, + LIGHT_ID_NOTIFICATIONS, LIGHT_ID_ATTENTION, LIGHT_ID_BLUETOOTH, + LIGHT_ID_WIFI}; + size_t led_index = 0; + for (const char* light_name : kLogicalLights) { + light_device_t* light_device = nullptr; + ret = lights_hal_->methods->open( + lights_hal_, light_name, + reinterpret_cast<hw_device_t**>(&light_device)); + // If a given light device couldn't be opened, don't map it to a number. + if (ret || !light_device) { + continue; + } + hal_led_map_.emplace(led_index, light_name); + led_index++; + if (led_index == num_leds) { + // We have already mapped all num_leds LEDs. + break; + } + } + + // If the size of the map is zero, then the lights hal doesn't have any valid + // leds. + if (hal_led_map_.empty()) { + LOG(ERROR) << "Unable to open any light devices using the hal."; + lights_hal_ = nullptr; + return; + } + + // If not all 4 numbers have been mapped, then we map them to the first led + // mapped. + for (size_t i = hal_led_map_.size(); i < num_leds; i++) { + hal_led_map_.emplace(i, hal_led_map_[0]); + } + hal_led_status_.resize(num_leds); +} + std::vector<bool> LedStatus::GetStatus() const { + if (lights_hal_) + return hal_led_status_; + std::vector<bool> leds(num_leds); for (size_t index = 0; index < num_leds; index++) leds[index] = IsLedOn(index); @@ -75,6 +129,37 @@ bool LedStatus::IsLedOn(size_t index) const { } void LedStatus::SetLedStatus(size_t index, bool on) { + if (lights_hal_) { + light_state_t state = {}; + state.color = on; + state.flashMode = LIGHT_FLASH_NONE; + state.flashOnMS = 0; + state.flashOffMS = 0; + state.brightnessMode = BRIGHTNESS_MODE_USER; + light_device_t* light_device = nullptr; + int rc = lights_hal_->methods->open( + lights_hal_, hal_led_map_[index].c_str(), + reinterpret_cast<hw_device_t**>(&light_device)); + if (rc) { + LOG(ERROR) << "Unable to open " << hal_led_map_[index]; + return; + } + CHECK(light_device); + rc = light_device->set_light(light_device, &state); + if (rc) { + LOG(ERROR) << "Unable to set " << hal_led_map_[index]; + return; + } + hal_led_status_[index] = on; + light_device->common.close( + reinterpret_cast<hw_device_t*>(light_device)); + if (rc) { + LOG(ERROR) << "Unable to close " << hal_led_map_[index]; + return; + } + return; + } + brillo::StreamPtr stream = GetLEDDataStream(index, true); if (!stream) return; diff --git a/src/ledservice/ledstatus.h b/src/ledservice/ledstatus.h index f12e9581a473fb0d0b7bb16c40cd8ca51615b154..dc9a472645151a5bbbe237d858ca4893012af042 100644 --- a/src/ledservice/ledstatus.h +++ b/src/ledservice/ledstatus.h @@ -17,13 +17,15 @@ #ifndef LEDFLASHER_SRC_LEDSERVICE_LEDSTATUS_H_ #define LEDFLASHER_SRC_LEDSERVICE_LEDSTATUS_H_ +#include <map> #include <vector> #include <base/macros.h> +#include <hardware/lights.h> class LedStatus final { public: - LedStatus() = default; + LedStatus(); std::vector<bool> GetStatus() const; bool IsLedOn(size_t index) const; @@ -32,6 +34,13 @@ class LedStatus final { static const size_t num_leds = 4; private: + const hw_module_t* lights_hal_{nullptr}; + // Maps the lights available to the hal to numbers 1 - 4. It is possible for + // multiple numbers to be mapped to the same led on the board. + std::map<size_t, std::string> hal_led_map_; + // Since the hal doesn't have a way to track the led status, we maintain that + // info here. + std::vector<bool> hal_led_status_; DISALLOW_COPY_AND_ASSIGN(LedStatus); };