From 72d5a0e9b7fc812a880ab4e1f5795324e5ebf9a9 Mon Sep 17 00:00:00 2001 From: Shawn S <shawnshen@google.com> Date: Tue, 23 Feb 2016 11:06:43 -0800 Subject: [PATCH] Updated ledflasher sample to use trait/component model - light schema onOff trait - dynamically add components based on available LEDs from lights HAL - custom trait _ledInfo to save lights HAL LED names BUG:26798554 Change-Id: I4c1dd0cdb2f3479703e9082fea152a713178e65c --- .../examples/ledflasher/ILEDService.aidl | 3 + src/ledflasher/animation.cpp | 4 + src/ledflasher/animation.h | 2 +- src/ledflasher/animation_marquee.cpp | 3 +- .../etc/weaved/traits/ledflasher.json | 53 ++++--- src/ledflasher/ledflasher.cpp | 145 +++++++++++------- src/ledservice/ledservice.cpp | 20 +++ src/ledservice/ledstatus.cpp | 56 +++---- src/ledservice/ledstatus.h | 14 +- 9 files changed, 181 insertions(+), 119 deletions(-) diff --git a/src/common/aidl/brillo/examples/ledflasher/ILEDService.aidl b/src/common/aidl/brillo/examples/ledflasher/ILEDService.aidl index 5ec561b..84a5092 100644 --- a/src/common/aidl/brillo/examples/ledflasher/ILEDService.aidl +++ b/src/common/aidl/brillo/examples/ledflasher/ILEDService.aidl @@ -17,7 +17,10 @@ package brillo.examples.ledflasher; interface ILEDService { + int getLEDCount(); void setLED(int ledIndex, boolean on); boolean getLED(int ledIndex); boolean[] getAllLEDs(); + String[] getAllLEDNames(); + void setAllLEDs(boolean on); } diff --git a/src/ledflasher/animation.cpp b/src/ledflasher/animation.cpp index 34513d2..b76589e 100644 --- a/src/ledflasher/animation.cpp +++ b/src/ledflasher/animation.cpp @@ -25,6 +25,10 @@ Animation::Animation( android::sp<brillo::examples::ledflasher::ILEDService> led_service, const base::TimeDelta& step_duration) : led_service_{led_service}, step_duration_{step_duration} { + int led_count; + led_service_->getLEDCount(&led_count); + num_leds = static_cast<size_t>(led_count); + step_duration_ /= num_leds; } Animation::~Animation() { diff --git a/src/ledflasher/animation.h b/src/ledflasher/animation.h index 190e9a6..30a3b40 100644 --- a/src/ledflasher/animation.h +++ b/src/ledflasher/animation.h @@ -39,9 +39,9 @@ class Animation { const std::string& type, const base::TimeDelta& duration); - static const size_t num_leds = 4; protected: + size_t num_leds; virtual void DoAnimationStep() = 0; bool GetLED(size_t index) const; diff --git a/src/ledflasher/animation_marquee.cpp b/src/ledflasher/animation_marquee.cpp index 77df265..37674e2 100644 --- a/src/ledflasher/animation_marquee.cpp +++ b/src/ledflasher/animation_marquee.cpp @@ -20,8 +20,7 @@ AnimationMarquee::AnimationMarquee( android::sp<brillo::examples::ledflasher::ILEDService> led_service, const base::TimeDelta& duration, Direction direction) - : Animation{led_service, duration / num_leds}, direction_{direction} { -} + : Animation{led_service, duration}, direction_{direction} {} void AnimationMarquee::DoAnimationStep() { SetAllLEDs(false); diff --git a/src/ledflasher/etc/weaved/traits/ledflasher.json b/src/ledflasher/etc/weaved/traits/ledflasher.json index ff4ac68..0d5974a 100644 --- a/src/ledflasher/etc/weaved/traits/ledflasher.json +++ b/src/ledflasher/etc/weaved/traits/ledflasher.json @@ -1,27 +1,6 @@ { "_ledflasher": { "commands": { - "set": { - "minimalRole": "user", - "parameters": { - "led": { - "type": "integer", - "minimum": 1, - "maximum": 4 - }, - "on": { "type": "boolean" } - } - }, - "toggle": { - "minimalRole": "user", - "parameters": { - "led": { - "type": "integer", - "minimum": 1, - "maximum": 4 - } - } - }, "animate": { "minimalRole": "user", "parameters": { @@ -41,10 +20,34 @@ "status": { "type": "string", "enum": [ "idle", "animating" ] - }, - "leds": { - "type": "array", - "items": { "type": "boolean" } + } + } + }, + "onOff": { + "commands": { + "setConfig": { + "minimalRole": "user", + "parameters": { + "state": { + "type": "string", + "enum": [ "on", "off" ] + } + } + } + }, + "state": { + "state": { + "isRequired": true, + "type": "string", + "enum": [ "on", "off" ] + } + } + }, + "_ledInfo": { + "state": { + "name": { + "isRequired": true, + "type": "string" } } } diff --git a/src/ledflasher/ledflasher.cpp b/src/ledflasher/ledflasher.cpp index de495f3..bce3420 100644 --- a/src/ledflasher/ledflasher.cpp +++ b/src/ledflasher/ledflasher.cpp @@ -31,11 +31,16 @@ #include "binder_constants.h" #include "brillo/examples/ledflasher/ILEDService.h" +using android::String16; + namespace { -const char kWeaveComponent[] = "ledflasher"; -const char kWeaveTrait[] = "_ledflasher"; +const char kLedFlasherComponent[] = "ledflasher"; +const char kLedFlasherTrait[] = "_ledflasher"; const char kBaseComponent[] = "base"; const char kBaseTrait[] = "base"; +const char kLedComponentPrefix[] = "led"; +const char kOnOffTrait[] = "onOff"; +const char kLedInfoTrait[] = "_ledInfo"; } // anonymous namespace using brillo::examples::ledflasher::ILEDService; @@ -52,10 +57,10 @@ class Daemon final : public brillo::Daemon { void ConnectToLEDService(); void OnLEDServiceDisconnected(); void OnPairingInfoChanged(const weaved::Service::PairingInfo* pairing_info); + void CreateLedComponentsIfNeeded(); // Particular command handlers for various commands. - void OnSet(std::unique_ptr<weaved::Command> command); - void OnToggle(std::unique_ptr<weaved::Command> command); + void OnSetConfig(size_t led_index, std::unique_ptr<weaved::Command> command); void OnAnimate(std::unique_ptr<weaved::Command> command); void OnIdentify(std::unique_ptr<weaved::Command> command); @@ -80,6 +85,8 @@ class Daemon final : public brillo::Daemon { brillo::BinderWatcher binder_watcher_; std::unique_ptr<weaved::Service::Subscription> weave_service_subscription_; + bool led_components_added_{false}; + base::WeakPtrFactory<Daemon> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(Daemon); }; @@ -111,15 +118,12 @@ void Daemon::OnWeaveServiceConnected( if (!weave_service) return; - weave_service->AddComponent(kWeaveComponent, {kWeaveTrait}, nullptr); - weave_service->AddCommandHandler( - kWeaveComponent, kWeaveTrait, "set", - base::Bind(&Daemon::OnSet, weak_ptr_factory_.GetWeakPtr())); + weave_service->AddComponent( + kLedFlasherComponent, {kLedFlasherTrait}, nullptr); weave_service->AddCommandHandler( - kWeaveComponent, kWeaveTrait, "toggle", - base::Bind(&Daemon::OnToggle, weak_ptr_factory_.GetWeakPtr())); - weave_service->AddCommandHandler( - kWeaveComponent, kWeaveTrait, "animate", + kLedFlasherComponent, + kLedFlasherTrait, + "animate", base::Bind(&Daemon::OnAnimate, weak_ptr_factory_.GetWeakPtr())); weave_service->AddCommandHandler( kBaseComponent, kBaseTrait, "identify", @@ -129,6 +133,8 @@ void Daemon::OnWeaveServiceConnected( base::Bind(&Daemon::OnPairingInfoChanged, weak_ptr_factory_.GetWeakPtr())); + led_components_added_ = false; + CreateLedComponentsIfNeeded(); UpdateDeviceState(); } @@ -147,61 +153,92 @@ void Daemon::ConnectToLEDService() { base::Bind(&Daemon::OnLEDServiceDisconnected, weak_ptr_factory_.GetWeakPtr())); led_service_ = android::interface_cast<ILEDService>(binder); + CreateLedComponentsIfNeeded(); UpdateDeviceState(); } +void Daemon::CreateLedComponentsIfNeeded() { + if (led_components_added_ || !led_service_.get()) + return; + + auto weave_service = weave_service_.lock(); + if (!weave_service) + return; + + std::vector<bool> leds; + std::vector<String16> ledNames; + if (!led_service_->getAllLEDs(&leds).isOk()) + return; + + if (!led_service_->getAllLEDNames(&ledNames).isOk()) + return; + + for (size_t led_index = 0; led_index < leds.size(); led_index++) { + std::string led_name = android::String8{ledNames[led_index]}.string(); + std::string component_name = + kLedComponentPrefix + std::to_string(led_index + 1); + if (weave_service->AddComponent( + component_name, {kOnOffTrait, kLedInfoTrait}, nullptr)) { + weave_service->AddCommandHandler( + component_name, + kOnOffTrait, + "setConfig", + base::Bind( + &Daemon::OnSetConfig, weak_ptr_factory_.GetWeakPtr(), led_index)); + + weave_service->SetStateProperty( + component_name, + kOnOffTrait, + "state", + *brillo::ToValue(leds[led_index] ? "on" : "off"), + nullptr); + + weave_service->SetStateProperty(component_name, + kLedInfoTrait, + "name", + *brillo::ToValue(led_name), + nullptr); + } + } + led_components_added_ = true; +} + void Daemon::OnLEDServiceDisconnected() { animation_.reset(); led_service_ = nullptr; ConnectToLEDService(); } -void Daemon::OnSet(std::unique_ptr<weaved::Command> command) { +void Daemon::OnSetConfig(size_t led_index, + std::unique_ptr<weaved::Command> command) { if (!led_service_.get()) { command->Abort("_system_error", "ledservice unavailable", nullptr); return; } - int index = command->GetParameter<int>("led"); - if(index < 1 || index > 4) { - command->Abort("_invalid_parameter", "Invalid parameter value", nullptr); - return; - } - bool on = command->GetParameter<bool>("on"); - android::binder::Status status = led_service_->setLED(index - 1, on); + auto state = command->GetParameter<std::string>("state"); + bool on = (state == "on"); + android::binder::Status status = led_service_->setLED(led_index, on); if (!status.isOk()) { command->AbortWithCustomError(status, nullptr); return; } - animation_.reset(); - status_ = "idle"; - UpdateDeviceState(); - command->Complete({}, nullptr); -} - -void Daemon::OnToggle(std::unique_ptr<weaved::Command> command) { - if (!led_service_.get()) { - command->Abort("_system_error", "ledservice unavailable", nullptr); - return; + if (animation_) { + animation_.reset(); + status_ = "idle"; + UpdateDeviceState(); } - int index = command->GetParameter<int>("led"); - if(index < 1 || index > 4) { - command->Abort("_invalid_parameter", "Invalid parameter value", nullptr); - return; - } - index--; - bool on = false; - android::binder::Status status = led_service_->getLED(index, &on); - if (status.isOk()) - status = led_service_->setLED(index, !on); - if(!status.isOk()) { - command->AbortWithCustomError(status, nullptr); - return; + auto weave_service = weave_service_.lock(); + if (weave_service) { + std::string component_name = + kLedComponentPrefix + std::to_string(led_index + 1); + weave_service->SetStateProperty(component_name, + kOnOffTrait, + "state", + *brillo::ToValue(on ? "on" : "off"), + nullptr); } - animation_.reset(); - status_ = "idle"; - UpdateDeviceState(); command->Complete({}, nullptr); } @@ -263,21 +300,15 @@ void Daemon::StopAnimation() { } void Daemon::UpdateDeviceState() { - if (!led_service_.get()) - return; - - std::vector<bool> leds; - if (!led_service_->getAllLEDs(&leds).isOk()) - return; - auto weave_service = weave_service_.lock(); if (!weave_service) return; - base::DictionaryValue state_change; - state_change.SetString("_ledflasher.status", status_); - state_change.Set("_ledflasher.leds", brillo::ToValue(leds).release()); - weave_service->SetStateProperties(kWeaveComponent, state_change, nullptr); + weave_service->SetStateProperty(kLedFlasherComponent, + kLedFlasherTrait, + "status", + *brillo::ToValue(status_), + nullptr); } int main(int argc, char* argv[]) { diff --git a/src/ledservice/ledservice.cpp b/src/ledservice/ledservice.cpp index cdc2924..065606a 100644 --- a/src/ledservice/ledservice.cpp +++ b/src/ledservice/ledservice.cpp @@ -29,8 +29,15 @@ #include "brillo/examples/ledflasher/BnLEDService.h" #include "ledstatus.h" +using android::String16; + class LEDService : public brillo::examples::ledflasher::BnLEDService { public: + android::binder::Status getLEDCount(int32_t* count) override { + *count = leds_.GetLedCount(); + return android::binder::Status::ok(); + } + android::binder::Status setLED(int32_t ledIndex, bool on) override { leds_.SetLedStatus(ledIndex, on); return android::binder::Status::ok(); @@ -46,6 +53,19 @@ class LEDService : public brillo::examples::ledflasher::BnLEDService { return android::binder::Status::ok(); } + android::binder::Status getAllLEDNames(std::vector<String16>* leds) override { + std::vector<std::string> ledNames = leds_.GetNames(); + for (const std::string& name : ledNames) { + leds->push_back(String16{name.c_str()}); + } + return android::binder::Status::ok(); + } + + android::binder::Status setAllLEDs(bool on) override { + leds_.SetAllLeds(on); + return android::binder::Status::ok(); + } + private: LedStatus leds_; }; diff --git a/src/ledservice/ledstatus.cpp b/src/ledservice/ledstatus.cpp index 6ce65c6..f62c77c 100644 --- a/src/ledservice/ledstatus.cpp +++ b/src/ledservice/ledstatus.cpp @@ -30,7 +30,6 @@ namespace { brillo::StreamPtr GetLEDDataStream(size_t index, bool write) { - CHECK(index < LedStatus::num_leds); std::string led_path; if( index == 3 ) { led_path = "/sys/class/leds/boot/brightness"; @@ -48,7 +47,7 @@ brillo::StreamPtr GetLEDDataStream(size_t index, bool write) { } // anonymous namespace LedStatus::LedStatus() { - // Try to open the lights hal. + // 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."; @@ -57,14 +56,12 @@ LedStatus::LedStatus() { 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. + // If we can open the HAL, then we map each number to one of the LEDs + // available on the board. 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( @@ -74,41 +71,39 @@ LedStatus::LedStatus() { 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; - } + hal_leds_.push_back(light_name); + hal_led_status_.push_back(false); } - // If the size of the map is zero, then the lights hal doesn't have any valid + // 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."; + if (hal_leds_.empty()) { + LOG(INFO) << "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); +size_t LedStatus::GetLedCount() const { + return lights_hal_ ? hal_leds_.size() : 1; } 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++) + std::vector<bool> leds(GetLedCount()); + for (size_t index = 0; index < GetLedCount(); index++) leds[index] = IsLedOn(index); return leds; } +std::vector<std::string> LedStatus::GetNames() const { + return lights_hal_ ? hal_leds_ : std::vector<std::string>(GetLedCount()); +} + bool LedStatus::IsLedOn(size_t index) const { + CHECK(index < GetLedCount()); if (lights_hal_) return hal_led_status_[index]; @@ -132,6 +127,7 @@ bool LedStatus::IsLedOn(size_t index) const { } void LedStatus::SetLedStatus(size_t index, bool on) { + CHECK(index < GetLedCount()); if (lights_hal_) { light_state_t state = {}; state.color = on; @@ -141,23 +137,24 @@ void LedStatus::SetLedStatus(size_t index, bool on) { 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(), + lights_hal_, + hal_leds_[index].c_str(), reinterpret_cast<hw_device_t**>(&light_device)); if (rc) { - LOG(ERROR) << "Unable to open " << hal_led_map_[index]; + LOG(ERROR) << "Unable to open " << hal_leds_[index]; return; } CHECK(light_device); rc = light_device->set_light(light_device, &state); if (rc) { - LOG(ERROR) << "Unable to set " << hal_led_map_[index]; + LOG(ERROR) << "Unable to set " << hal_leds_[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]; + LOG(ERROR) << "Unable to close " << hal_leds_[index]; return; } return; @@ -170,3 +167,8 @@ void LedStatus::SetLedStatus(size_t index, bool on) { std::string brightness = on ? "255" : "0"; stream->WriteAllBlocking(brightness.data(), brightness.size(), nullptr); } + +void LedStatus::SetAllLeds(bool on) { + for (size_t i = 0; i < GetLedCount(); i++) + SetLedStatus(i, on); +} diff --git a/src/ledservice/ledstatus.h b/src/ledservice/ledstatus.h index dc9a472..8e9c26a 100644 --- a/src/ledservice/ledstatus.h +++ b/src/ledservice/ledstatus.h @@ -17,7 +17,7 @@ #ifndef LEDFLASHER_SRC_LEDSERVICE_LEDSTATUS_H_ #define LEDFLASHER_SRC_LEDSERVICE_LEDSTATUS_H_ -#include <map> +#include <string> #include <vector> #include <base/macros.h> @@ -28,17 +28,17 @@ class LedStatus final { LedStatus(); std::vector<bool> GetStatus() const; + std::vector<std::string> GetNames() const; bool IsLedOn(size_t index) const; void SetLedStatus(size_t index, bool on); - - static const size_t num_leds = 4; + void SetAllLeds(bool on); + size_t GetLedCount() const; 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 + // Contains the names of LEDs in the HAL for each of supported LEDs. + std::vector<std::string> hal_leds_; + // Since the HAL doesn't have a way to track the led status, we maintain that // info here. std::vector<bool> hal_led_status_; -- GitLab