blob: a380b5eadf034d2d26f532c7a27afc08a981216e [file] [log] [blame]
Chris Yee2b1e5c2021-03-10 22:45:12 -08001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <locale>
18#include <regex>
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000019#include <set>
Chris Yee2b1e5c2021-03-10 22:45:12 -080020
Dominik Laskowski75788452021-02-09 18:51:25 -080021#include <ftl/enum.h>
Chris Yee2b1e5c2021-03-10 22:45:12 -080022
Dominik Laskowski75788452021-02-09 18:51:25 -080023#include "../Macros.h"
Chris Ye1dd2e5c2021-04-04 23:12:41 -070024#include "PeripheralController.h"
Chris Yee2b1e5c2021-03-10 22:45:12 -080025
Chris Yee2b1e5c2021-03-10 22:45:12 -080026namespace android {
27
28static inline int32_t getAlpha(int32_t color) {
29 return (color >> 24) & 0xff;
30}
31
32static inline int32_t getRed(int32_t color) {
33 return (color >> 16) & 0xff;
34}
35
36static inline int32_t getGreen(int32_t color) {
37 return (color >> 8) & 0xff;
38}
39
40static inline int32_t getBlue(int32_t color) {
41 return color & 0xff;
42}
43
44static inline int32_t toArgb(int32_t brightness, int32_t red, int32_t green, int32_t blue) {
45 return (brightness & 0xff) << 24 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff);
46}
47
48/**
49 * Input controller owned by InputReader device, implements the native API for querying input
50 * lights, getting and setting the lights brightness and color, by interacting with EventHub
51 * devices.
52 */
Chris Ye1dd2e5c2021-04-04 23:12:41 -070053PeripheralController::PeripheralController(InputDeviceContext& deviceContext)
Chris Yee2b1e5c2021-03-10 22:45:12 -080054 : mDeviceContext(deviceContext) {
55 configureBattries();
56 configureLights();
57}
58
Chris Ye1dd2e5c2021-04-04 23:12:41 -070059PeripheralController::~PeripheralController() {}
Chris Yee2b1e5c2021-03-10 22:45:12 -080060
Chris Ye1dd2e5c2021-04-04 23:12:41 -070061std::optional<std::int32_t> PeripheralController::Light::getRawLightBrightness(int32_t rawLightId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080062 std::optional<RawLightInfo> rawInfoOpt = context.getRawLightInfo(rawLightId);
63 if (!rawInfoOpt.has_value()) {
64 return std::nullopt;
65 }
66 std::optional<int32_t> brightnessOpt = context.getLightBrightness(rawLightId);
67 if (!brightnessOpt.has_value()) {
68 return std::nullopt;
69 }
70 int brightness = brightnessOpt.value();
71
72 // If the light node doesn't have max brightness, use the default max brightness.
73 int rawMaxBrightness = rawInfoOpt->maxBrightness.value_or(MAX_BRIGHTNESS);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000074 float ratio = static_cast<float>(MAX_BRIGHTNESS) / rawMaxBrightness;
Chris Yee2b1e5c2021-03-10 22:45:12 -080075 // Scale the returned brightness in [0, rawMaxBrightness] to [0, 255]
76 if (rawMaxBrightness != MAX_BRIGHTNESS) {
77 brightness = brightness * ratio;
78 }
79 if (DEBUG_LIGHT_DETAILS) {
80 ALOGD("getRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f", rawLightId,
81 brightness, ratio);
82 }
83 return brightness;
84}
85
Chris Ye1dd2e5c2021-04-04 23:12:41 -070086void PeripheralController::Light::setRawLightBrightness(int32_t rawLightId, int32_t brightness) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080087 std::optional<RawLightInfo> rawInfo = context.getRawLightInfo(rawLightId);
88 if (!rawInfo.has_value()) {
89 return;
90 }
91 // If the light node doesn't have max brightness, use the default max brightness.
92 int rawMaxBrightness = rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000093 float ratio = static_cast<float>(MAX_BRIGHTNESS) / rawMaxBrightness;
Chris Yee2b1e5c2021-03-10 22:45:12 -080094 // Scale the requested brightness in [0, 255] to [0, rawMaxBrightness]
95 if (rawMaxBrightness != MAX_BRIGHTNESS) {
96 brightness = ceil(brightness / ratio);
97 }
98 if (DEBUG_LIGHT_DETAILS) {
99 ALOGD("setRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f", rawLightId,
100 brightness, ratio);
101 }
102 context.setLightBrightness(rawLightId, brightness);
103}
104
Chris Ye85758332021-05-16 23:05:17 -0700105bool PeripheralController::MonoLight::setLightColor(int32_t color) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800106 int32_t brightness = getAlpha(color);
107 setRawLightBrightness(rawId, brightness);
108
109 return true;
110}
111
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700112bool PeripheralController::RgbLight::setLightColor(int32_t color) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800113 // Compose color value as per:
114 // https://developer.android.com/reference/android/graphics/Color?hl=en
115 // int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);
116 // The alpha component is used to scale the R,G,B leds brightness, with the ratio to
117 // MAX_BRIGHTNESS.
118 brightness = getAlpha(color);
119 int32_t red = 0;
120 int32_t green = 0;
121 int32_t blue = 0;
122 if (brightness > 0) {
123 float ratio = MAX_BRIGHTNESS / brightness;
124 red = ceil(getRed(color) / ratio);
125 green = ceil(getGreen(color) / ratio);
126 blue = ceil(getBlue(color) / ratio);
127 }
128 setRawLightBrightness(rawRgbIds.at(LightColor::RED), red);
129 setRawLightBrightness(rawRgbIds.at(LightColor::GREEN), green);
130 setRawLightBrightness(rawRgbIds.at(LightColor::BLUE), blue);
131 if (rawGlobalId.has_value()) {
132 setRawLightBrightness(rawGlobalId.value(), brightness);
133 }
134
135 return true;
136}
137
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700138bool PeripheralController::MultiColorLight::setLightColor(int32_t color) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800139 std::unordered_map<LightColor, int32_t> intensities;
140 intensities.emplace(LightColor::RED, getRed(color));
141 intensities.emplace(LightColor::GREEN, getGreen(color));
142 intensities.emplace(LightColor::BLUE, getBlue(color));
143
144 context.setLightIntensities(rawId, intensities);
145 setRawLightBrightness(rawId, getAlpha(color));
146 return true;
147}
148
Chris Ye85758332021-05-16 23:05:17 -0700149std::optional<int32_t> PeripheralController::MonoLight::getLightColor() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800150 std::optional<int32_t> brightness = getRawLightBrightness(rawId);
151 if (!brightness.has_value()) {
152 return std::nullopt;
153 }
154
Harry Cutts33476232023-01-30 19:57:29 +0000155 return toArgb(brightness.value(), /*red=*/0, /*green=*/0, /*blue=*/0);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800156}
157
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700158std::optional<int32_t> PeripheralController::RgbLight::getLightColor() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800159 // If the Alpha component is zero, then return color 0.
160 if (brightness == 0) {
161 return 0;
162 }
163 // Compose color value as per:
164 // https://developer.android.com/reference/android/graphics/Color?hl=en
165 // int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);
166 std::optional<int32_t> redOr = getRawLightBrightness(rawRgbIds.at(LightColor::RED));
167 std::optional<int32_t> greenOr = getRawLightBrightness(rawRgbIds.at(LightColor::GREEN));
168 std::optional<int32_t> blueOr = getRawLightBrightness(rawRgbIds.at(LightColor::BLUE));
169 // If we can't get brightness for any of the RGB light
170 if (!redOr.has_value() || !greenOr.has_value() || !blueOr.has_value()) {
171 return std::nullopt;
172 }
173
174 // Compose the ARGB format color. As the R,G,B color led brightness is scaled by Alpha
175 // value, scale it back to return the nominal color value.
176 float ratio = MAX_BRIGHTNESS / brightness;
177 int32_t red = round(redOr.value() * ratio);
178 int32_t green = round(greenOr.value() * ratio);
179 int32_t blue = round(blueOr.value() * ratio);
180
181 if (red > MAX_BRIGHTNESS || green > MAX_BRIGHTNESS || blue > MAX_BRIGHTNESS) {
182 // Previously stored brightness isn't valid for current LED values, so just reset to max
183 // brightness since an app couldn't have provided these values in the first place.
184 red = redOr.value();
185 green = greenOr.value();
186 blue = blueOr.value();
187 brightness = MAX_BRIGHTNESS;
188 }
189
190 return toArgb(brightness, red, green, blue);
191}
192
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700193std::optional<int32_t> PeripheralController::MultiColorLight::getLightColor() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800194 auto ret = context.getLightIntensities(rawId);
195 if (!ret.has_value()) {
196 return std::nullopt;
197 }
198 std::unordered_map<LightColor, int32_t> intensities = ret.value();
199 // Get red, green, blue colors
Harry Cutts33476232023-01-30 19:57:29 +0000200 int32_t color = toArgb(/*brightness=*/0, intensities.at(LightColor::RED),
201 intensities.at(LightColor::GREEN), intensities.at(LightColor::BLUE));
Chris Yee2b1e5c2021-03-10 22:45:12 -0800202 // Get brightness
203 std::optional<int32_t> brightness = getRawLightBrightness(rawId);
204 if (brightness.has_value()) {
Harry Cutts33476232023-01-30 19:57:29 +0000205 return toArgb(/*brightness=*/brightness.value(), 0, 0, 0) | color;
Chris Yee2b1e5c2021-03-10 22:45:12 -0800206 }
207 return std::nullopt;
208}
209
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700210bool PeripheralController::PlayerIdLight::setLightPlayerId(int32_t playerId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800211 if (rawLightIds.find(playerId) == rawLightIds.end()) {
212 return false;
213 }
214 for (const auto& [id, rawId] : rawLightIds) {
215 if (playerId == id) {
216 setRawLightBrightness(rawId, MAX_BRIGHTNESS);
217 } else {
218 setRawLightBrightness(rawId, 0);
219 }
220 }
221 return true;
222}
223
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700224std::optional<int32_t> PeripheralController::PlayerIdLight::getLightPlayerId() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800225 for (const auto& [id, rawId] : rawLightIds) {
226 std::optional<int32_t> brightness = getRawLightBrightness(rawId);
227 if (brightness.has_value() && brightness.value() > 0) {
228 return id;
229 }
230 }
231 return std::nullopt;
232}
233
Chris Ye85758332021-05-16 23:05:17 -0700234void PeripheralController::MonoLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800235 dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
236}
237
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700238void PeripheralController::PlayerIdLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800239 dump += StringPrintf(INDENT4 "PlayerId: %d\n", getLightPlayerId().value_or(-1));
240 dump += StringPrintf(INDENT4 "Raw Player ID LEDs:");
241 for (const auto& [id, rawId] : rawLightIds) {
242 dump += StringPrintf("id %d -> %d ", id, rawId);
243 }
244 dump += "\n";
245}
246
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700247void PeripheralController::RgbLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800248 dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
249 dump += StringPrintf(INDENT4 "Raw RGB LEDs: [%d, %d, %d] ", rawRgbIds.at(LightColor::RED),
250 rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
251 if (rawGlobalId.has_value()) {
252 dump += StringPrintf(INDENT4 "Raw Global LED: [%d] ", rawGlobalId.value());
253 }
254 dump += "\n";
255}
256
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700257void PeripheralController::MultiColorLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800258 dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
259}
260
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700261void PeripheralController::populateDeviceInfo(InputDeviceInfo* deviceInfo) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800262 // TODO: b/180733860 Remove this after enabling multi-battery
263 if (!mBatteries.empty()) {
264 deviceInfo->setHasBattery(true);
265 }
266
267 for (const auto& [batteryId, battery] : mBatteries) {
268 InputDeviceBatteryInfo batteryInfo(battery->name, battery->id);
269 deviceInfo->addBatteryInfo(batteryInfo);
270 }
271
272 for (const auto& [lightId, light] : mLights) {
273 // Input device light doesn't support ordinal, always pass 1.
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000274 InputDeviceLightInfo lightInfo(light->name, light->id, light->type, light->capabilityFlags,
Harry Cutts33476232023-01-30 19:57:29 +0000275 /*ordinal=*/1);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800276 deviceInfo->addLightInfo(lightInfo);
277 }
278}
279
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700280void PeripheralController::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800281 dump += INDENT2 "Input Controller:\n";
282 if (!mLights.empty()) {
283 dump += INDENT3 "Lights:\n";
284 for (const auto& [lightId, light] : mLights) {
285 dump += StringPrintf(INDENT4 "Id: %d", lightId);
286 dump += StringPrintf(INDENT4 "Name: %s", light->name.c_str());
Dominik Laskowski75788452021-02-09 18:51:25 -0800287 dump += StringPrintf(INDENT4 "Type: %s", ftl::enum_string(light->type).c_str());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000288 dump += StringPrintf(INDENT4 "Capability flags: %s",
289 light->capabilityFlags.string().c_str());
Chris Yee2b1e5c2021-03-10 22:45:12 -0800290 light->dump(dump);
291 }
292 }
293 // Dump raw lights
294 dump += INDENT3 "RawLights:\n";
295 dump += INDENT4 "Id:\t Name:\t Flags:\t Max brightness:\t Brightness\n";
296 const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
297 // Map from raw light id to raw light info
298 std::unordered_map<int32_t, RawLightInfo> rawInfos;
299 for (const auto& rawId : rawLightIds) {
300 std::optional<RawLightInfo> rawInfo = getDeviceContext().getRawLightInfo(rawId);
301 if (!rawInfo.has_value()) {
302 continue;
303 }
304 dump += StringPrintf(INDENT4 "%d", rawId);
305 dump += StringPrintf(INDENT4 "%s", rawInfo->name.c_str());
306 dump += StringPrintf(INDENT4 "%s", rawInfo->flags.string().c_str());
307 dump += StringPrintf(INDENT4 "%d", rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS));
308 dump += StringPrintf(INDENT4 "%d\n",
309 getDeviceContext().getLightBrightness(rawId).value_or(-1));
310 }
311
312 if (!mBatteries.empty()) {
313 dump += INDENT3 "Batteries:\n";
314 for (const auto& [batteryId, battery] : mBatteries) {
315 dump += StringPrintf(INDENT4 "Id: %d", batteryId);
316 dump += StringPrintf(INDENT4 "Name: %s", battery->name.c_str());
317 dump += getBatteryCapacity(batteryId).has_value()
318 ? StringPrintf(INDENT3 "Capacity: %d\n", getBatteryCapacity(batteryId).value())
319 : StringPrintf(INDENT3 "Capacity: Unknown");
320
321 std::string status;
322 switch (getBatteryStatus(batteryId).value_or(BATTERY_STATUS_UNKNOWN)) {
323 case BATTERY_STATUS_CHARGING:
324 status = "Charging";
325 break;
326 case BATTERY_STATUS_DISCHARGING:
327 status = "Discharging";
328 break;
329 case BATTERY_STATUS_NOT_CHARGING:
330 status = "Not charging";
331 break;
332 case BATTERY_STATUS_FULL:
333 status = "Full";
334 break;
335 default:
336 status = "Unknown";
337 }
338 dump += StringPrintf(INDENT3 "Status: %s\n", status.c_str());
339 }
340 }
341}
342
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700343void PeripheralController::configureBattries() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800344 // Check raw batteries
345 const std::vector<int32_t> rawBatteryIds = getDeviceContext().getRawBatteryIds();
346
347 for (const auto& rawId : rawBatteryIds) {
348 std::optional<RawBatteryInfo> rawInfo = getDeviceContext().getRawBatteryInfo(rawId);
349 if (!rawInfo.has_value()) {
350 continue;
351 }
352 std::unique_ptr<Battery> battery =
353 std::make_unique<Battery>(getDeviceContext(), rawInfo->name, rawInfo->id);
354 mBatteries.insert_or_assign(rawId, std::move(battery));
355 }
356}
357
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700358void PeripheralController::configureLights() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800359 bool hasRedLed = false;
360 bool hasGreenLed = false;
361 bool hasBlueLed = false;
362 std::optional<int32_t> rawGlobalId = std::nullopt;
363 // Player ID light common name string
364 std::string playerIdName;
365 // Raw RGB color to raw light ID
366 std::unordered_map<LightColor, int32_t /* rawLightId */> rawRgbIds;
367 // Map from player Id to raw light Id
368 std::unordered_map<int32_t, int32_t> playerIdLightIds;
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000369 // Set of Keyboard backlights
370 std::set<int32_t> keyboardBacklightIds;
Chris Yee2b1e5c2021-03-10 22:45:12 -0800371
372 // Check raw lights
373 const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
374 // Map from raw light id to raw light info
375 std::unordered_map<int32_t, RawLightInfo> rawInfos;
376 for (const auto& rawId : rawLightIds) {
377 std::optional<RawLightInfo> rawInfo = getDeviceContext().getRawLightInfo(rawId);
378 if (!rawInfo.has_value()) {
379 continue;
380 }
381 rawInfos.insert_or_assign(rawId, rawInfo.value());
382 // Check if this is a group LEDs for player ID
383 std::regex lightPattern("([a-z]+)([0-9]+)");
384 std::smatch results;
385 if (std::regex_match(rawInfo->name, results, lightPattern)) {
386 std::string commonName = results[1].str();
387 int32_t playerId = std::stoi(results[2]);
388 if (playerIdLightIds.empty()) {
389 playerIdName = commonName;
390 playerIdLightIds.insert_or_assign(playerId, rawId);
391 } else {
392 // Make sure the player ID leds have common string name
393 if (playerIdName.compare(commonName) == 0 &&
394 playerIdLightIds.find(playerId) == playerIdLightIds.end()) {
395 playerIdLightIds.insert_or_assign(playerId, rawId);
396 }
397 }
398 }
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000399 // Check if this is a Keyboard backlight
400 if (rawInfo->flags.test(InputLightClass::KEYBOARD_BACKLIGHT)) {
401 keyboardBacklightIds.insert(rawId);
402 }
Chris Yee2b1e5c2021-03-10 22:45:12 -0800403 // Check if this is an LED of RGB light
404 if (rawInfo->flags.test(InputLightClass::RED)) {
405 hasRedLed = true;
406 rawRgbIds.emplace(LightColor::RED, rawId);
407 }
408 if (rawInfo->flags.test(InputLightClass::GREEN)) {
409 hasGreenLed = true;
410 rawRgbIds.emplace(LightColor::GREEN, rawId);
411 }
412 if (rawInfo->flags.test(InputLightClass::BLUE)) {
413 hasBlueLed = true;
414 rawRgbIds.emplace(LightColor::BLUE, rawId);
415 }
416 if (rawInfo->flags.test(InputLightClass::GLOBAL)) {
417 rawGlobalId = rawId;
418 }
419 if (DEBUG_LIGHT_DETAILS) {
420 ALOGD("Light rawId %d name %s max %d flags %s \n", rawInfo->id, rawInfo->name.c_str(),
421 rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS), rawInfo->flags.string().c_str());
422 }
423 }
424
425 // Construct a player ID light
426 if (playerIdLightIds.size() > 1) {
427 std::unique_ptr<Light> light =
428 std::make_unique<PlayerIdLight>(getDeviceContext(), playerIdName, ++mNextId,
429 playerIdLightIds);
430 mLights.insert_or_assign(light->id, std::move(light));
431 // Remove these raw lights from raw light info as they've been used to compose a
Chris Ye85758332021-05-16 23:05:17 -0700432 // Player ID light, so we do not expose these raw lights as mono lights.
Chris Yee2b1e5c2021-03-10 22:45:12 -0800433 for (const auto& [playerId, rawId] : playerIdLightIds) {
434 rawInfos.erase(rawId);
435 }
436 }
437 // Construct a RGB light for composed RGB light
438 if (hasRedLed && hasGreenLed && hasBlueLed) {
439 if (DEBUG_LIGHT_DETAILS) {
440 ALOGD("Rgb light ids [%d, %d, %d] \n", rawRgbIds.at(LightColor::RED),
441 rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
442 }
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000443 bool isKeyboardBacklight = keyboardBacklightIds.find(rawRgbIds.at(LightColor::RED)) !=
444 keyboardBacklightIds.end() &&
445 keyboardBacklightIds.find(rawRgbIds.at(LightColor::GREEN)) !=
446 keyboardBacklightIds.end() &&
447 keyboardBacklightIds.find(rawRgbIds.at(LightColor::BLUE)) !=
448 keyboardBacklightIds.end() &&
449 (!rawGlobalId.has_value() ||
450 keyboardBacklightIds.find(rawGlobalId.value()) != keyboardBacklightIds.end());
451
Chris Yee2b1e5c2021-03-10 22:45:12 -0800452 std::unique_ptr<Light> light =
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000453 std::make_unique<RgbLight>(getDeviceContext(), ++mNextId,
454 isKeyboardBacklight
455 ? InputDeviceLightType::KEYBOARD_BACKLIGHT
456 : InputDeviceLightType::INPUT,
457 rawRgbIds, rawGlobalId);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800458 mLights.insert_or_assign(light->id, std::move(light));
459 // Remove from raw light info as they've been composed a RBG light.
460 rawInfos.erase(rawRgbIds.at(LightColor::RED));
461 rawInfos.erase(rawRgbIds.at(LightColor::GREEN));
462 rawInfos.erase(rawRgbIds.at(LightColor::BLUE));
463 if (rawGlobalId.has_value()) {
464 rawInfos.erase(rawGlobalId.value());
465 }
466 }
467
468 // Check the rest of raw light infos
469 for (const auto& [rawId, rawInfo] : rawInfos) {
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000470 InputDeviceLightType type = keyboardBacklightIds.find(rawId) != keyboardBacklightIds.end()
471 ? InputDeviceLightType::KEYBOARD_BACKLIGHT
472 : InputDeviceLightType::INPUT;
473
Chris Yee2b1e5c2021-03-10 22:45:12 -0800474 // If the node is multi-color led, construct a MULTI_COLOR light
475 if (rawInfo.flags.test(InputLightClass::MULTI_INDEX) &&
476 rawInfo.flags.test(InputLightClass::MULTI_INTENSITY)) {
477 if (DEBUG_LIGHT_DETAILS) {
478 ALOGD("Multicolor light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
479 }
480 std::unique_ptr<Light> light =
481 std::make_unique<MultiColorLight>(getDeviceContext(), rawInfo.name, ++mNextId,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000482 type, rawInfo.id);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800483 mLights.insert_or_assign(light->id, std::move(light));
484 continue;
485 }
Chris Ye85758332021-05-16 23:05:17 -0700486 // Construct a Mono LED light
Chris Yee2b1e5c2021-03-10 22:45:12 -0800487 if (DEBUG_LIGHT_DETAILS) {
Chris Ye85758332021-05-16 23:05:17 -0700488 ALOGD("Mono light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
Chris Yee2b1e5c2021-03-10 22:45:12 -0800489 }
Chris Ye85758332021-05-16 23:05:17 -0700490 std::unique_ptr<Light> light = std::make_unique<MonoLight>(getDeviceContext(), rawInfo.name,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000491 ++mNextId, type, rawInfo.id);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800492
493 mLights.insert_or_assign(light->id, std::move(light));
494 }
495}
496
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700497std::optional<int32_t> PeripheralController::getBatteryCapacity(int batteryId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800498 return getDeviceContext().getBatteryCapacity(batteryId);
499}
500
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700501std::optional<int32_t> PeripheralController::getBatteryStatus(int batteryId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800502 return getDeviceContext().getBatteryStatus(batteryId);
503}
504
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700505bool PeripheralController::setLightColor(int32_t lightId, int32_t color) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800506 auto it = mLights.find(lightId);
507 if (it == mLights.end()) {
508 return false;
509 }
510 auto& light = it->second;
511 if (DEBUG_LIGHT_DETAILS) {
512 ALOGD("setLightColor lightId %d type %s color 0x%x", lightId,
Dominik Laskowski75788452021-02-09 18:51:25 -0800513 ftl::enum_string(light->type).c_str(), color);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800514 }
515 return light->setLightColor(color);
516}
517
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700518std::optional<int32_t> PeripheralController::getLightColor(int32_t lightId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800519 auto it = mLights.find(lightId);
520 if (it == mLights.end()) {
521 return std::nullopt;
522 }
523 auto& light = it->second;
524 std::optional<int32_t> color = light->getLightColor();
525 if (DEBUG_LIGHT_DETAILS) {
526 ALOGD("getLightColor lightId %d type %s color 0x%x", lightId,
Dominik Laskowski75788452021-02-09 18:51:25 -0800527 ftl::enum_string(light->type).c_str(), color.value_or(0));
Chris Yee2b1e5c2021-03-10 22:45:12 -0800528 }
529 return color;
530}
531
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700532bool PeripheralController::setLightPlayerId(int32_t lightId, int32_t playerId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800533 auto it = mLights.find(lightId);
534 if (it == mLights.end()) {
535 return false;
536 }
537 auto& light = it->second;
538 return light->setLightPlayerId(playerId);
539}
540
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700541std::optional<int32_t> PeripheralController::getLightPlayerId(int32_t lightId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800542 auto it = mLights.find(lightId);
543 if (it == mLights.end()) {
544 return std::nullopt;
545 }
546 auto& light = it->second;
547 return light->getLightPlayerId();
548}
549
Andy Chenf9f1a022022-08-29 20:07:10 -0400550int32_t PeripheralController::getEventHubId() const {
551 return getDeviceContext().getEventHubId();
552}
553
Chris Yee2b1e5c2021-03-10 22:45:12 -0800554} // namespace android