blob: cedbacb046bdf679835ff903bac6c5ca5e225be2 [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
155 return toArgb(brightness.value(), 0 /* red */, 0 /* green */, 0 /* blue */);
156}
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
200 int32_t color = toArgb(0 /* brightness */, intensities.at(LightColor::RED) /* red */,
201 intensities.at(LightColor::GREEN) /* green */,
202 intensities.at(LightColor::BLUE) /* blue */);
203 // Get brightness
204 std::optional<int32_t> brightness = getRawLightBrightness(rawId);
205 if (brightness.has_value()) {
206 return toArgb(brightness.value() /* A */, 0, 0, 0) | color;
207 }
208 return std::nullopt;
209}
210
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700211bool PeripheralController::PlayerIdLight::setLightPlayerId(int32_t playerId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800212 if (rawLightIds.find(playerId) == rawLightIds.end()) {
213 return false;
214 }
215 for (const auto& [id, rawId] : rawLightIds) {
216 if (playerId == id) {
217 setRawLightBrightness(rawId, MAX_BRIGHTNESS);
218 } else {
219 setRawLightBrightness(rawId, 0);
220 }
221 }
222 return true;
223}
224
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700225std::optional<int32_t> PeripheralController::PlayerIdLight::getLightPlayerId() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800226 for (const auto& [id, rawId] : rawLightIds) {
227 std::optional<int32_t> brightness = getRawLightBrightness(rawId);
228 if (brightness.has_value() && brightness.value() > 0) {
229 return id;
230 }
231 }
232 return std::nullopt;
233}
234
Chris Ye85758332021-05-16 23:05:17 -0700235void PeripheralController::MonoLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800236 dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
237}
238
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700239void PeripheralController::PlayerIdLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800240 dump += StringPrintf(INDENT4 "PlayerId: %d\n", getLightPlayerId().value_or(-1));
241 dump += StringPrintf(INDENT4 "Raw Player ID LEDs:");
242 for (const auto& [id, rawId] : rawLightIds) {
243 dump += StringPrintf("id %d -> %d ", id, rawId);
244 }
245 dump += "\n";
246}
247
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700248void PeripheralController::RgbLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800249 dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
250 dump += StringPrintf(INDENT4 "Raw RGB LEDs: [%d, %d, %d] ", rawRgbIds.at(LightColor::RED),
251 rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
252 if (rawGlobalId.has_value()) {
253 dump += StringPrintf(INDENT4 "Raw Global LED: [%d] ", rawGlobalId.value());
254 }
255 dump += "\n";
256}
257
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700258void PeripheralController::MultiColorLight::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800259 dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
260}
261
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700262void PeripheralController::populateDeviceInfo(InputDeviceInfo* deviceInfo) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800263 // TODO: b/180733860 Remove this after enabling multi-battery
264 if (!mBatteries.empty()) {
265 deviceInfo->setHasBattery(true);
266 }
267
268 for (const auto& [batteryId, battery] : mBatteries) {
269 InputDeviceBatteryInfo batteryInfo(battery->name, battery->id);
270 deviceInfo->addBatteryInfo(batteryInfo);
271 }
272
273 for (const auto& [lightId, light] : mLights) {
274 // Input device light doesn't support ordinal, always pass 1.
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000275 InputDeviceLightInfo lightInfo(light->name, light->id, light->type, light->capabilityFlags,
276 1 /* ordinal */);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800277 deviceInfo->addLightInfo(lightInfo);
278 }
279}
280
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700281void PeripheralController::dump(std::string& dump) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800282 dump += INDENT2 "Input Controller:\n";
283 if (!mLights.empty()) {
284 dump += INDENT3 "Lights:\n";
285 for (const auto& [lightId, light] : mLights) {
286 dump += StringPrintf(INDENT4 "Id: %d", lightId);
287 dump += StringPrintf(INDENT4 "Name: %s", light->name.c_str());
Dominik Laskowski75788452021-02-09 18:51:25 -0800288 dump += StringPrintf(INDENT4 "Type: %s", ftl::enum_string(light->type).c_str());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000289 dump += StringPrintf(INDENT4 "Capability flags: %s",
290 light->capabilityFlags.string().c_str());
Chris Yee2b1e5c2021-03-10 22:45:12 -0800291 light->dump(dump);
292 }
293 }
294 // Dump raw lights
295 dump += INDENT3 "RawLights:\n";
296 dump += INDENT4 "Id:\t Name:\t Flags:\t Max brightness:\t Brightness\n";
297 const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
298 // Map from raw light id to raw light info
299 std::unordered_map<int32_t, RawLightInfo> rawInfos;
300 for (const auto& rawId : rawLightIds) {
301 std::optional<RawLightInfo> rawInfo = getDeviceContext().getRawLightInfo(rawId);
302 if (!rawInfo.has_value()) {
303 continue;
304 }
305 dump += StringPrintf(INDENT4 "%d", rawId);
306 dump += StringPrintf(INDENT4 "%s", rawInfo->name.c_str());
307 dump += StringPrintf(INDENT4 "%s", rawInfo->flags.string().c_str());
308 dump += StringPrintf(INDENT4 "%d", rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS));
309 dump += StringPrintf(INDENT4 "%d\n",
310 getDeviceContext().getLightBrightness(rawId).value_or(-1));
311 }
312
313 if (!mBatteries.empty()) {
314 dump += INDENT3 "Batteries:\n";
315 for (const auto& [batteryId, battery] : mBatteries) {
316 dump += StringPrintf(INDENT4 "Id: %d", batteryId);
317 dump += StringPrintf(INDENT4 "Name: %s", battery->name.c_str());
318 dump += getBatteryCapacity(batteryId).has_value()
319 ? StringPrintf(INDENT3 "Capacity: %d\n", getBatteryCapacity(batteryId).value())
320 : StringPrintf(INDENT3 "Capacity: Unknown");
321
322 std::string status;
323 switch (getBatteryStatus(batteryId).value_or(BATTERY_STATUS_UNKNOWN)) {
324 case BATTERY_STATUS_CHARGING:
325 status = "Charging";
326 break;
327 case BATTERY_STATUS_DISCHARGING:
328 status = "Discharging";
329 break;
330 case BATTERY_STATUS_NOT_CHARGING:
331 status = "Not charging";
332 break;
333 case BATTERY_STATUS_FULL:
334 status = "Full";
335 break;
336 default:
337 status = "Unknown";
338 }
339 dump += StringPrintf(INDENT3 "Status: %s\n", status.c_str());
340 }
341 }
342}
343
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700344void PeripheralController::configureBattries() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800345 // Check raw batteries
346 const std::vector<int32_t> rawBatteryIds = getDeviceContext().getRawBatteryIds();
347
348 for (const auto& rawId : rawBatteryIds) {
349 std::optional<RawBatteryInfo> rawInfo = getDeviceContext().getRawBatteryInfo(rawId);
350 if (!rawInfo.has_value()) {
351 continue;
352 }
353 std::unique_ptr<Battery> battery =
354 std::make_unique<Battery>(getDeviceContext(), rawInfo->name, rawInfo->id);
355 mBatteries.insert_or_assign(rawId, std::move(battery));
356 }
357}
358
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700359void PeripheralController::configureLights() {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800360 bool hasRedLed = false;
361 bool hasGreenLed = false;
362 bool hasBlueLed = false;
363 std::optional<int32_t> rawGlobalId = std::nullopt;
364 // Player ID light common name string
365 std::string playerIdName;
366 // Raw RGB color to raw light ID
367 std::unordered_map<LightColor, int32_t /* rawLightId */> rawRgbIds;
368 // Map from player Id to raw light Id
369 std::unordered_map<int32_t, int32_t> playerIdLightIds;
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000370 // Set of Keyboard backlights
371 std::set<int32_t> keyboardBacklightIds;
Chris Yee2b1e5c2021-03-10 22:45:12 -0800372
373 // Check raw lights
374 const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
375 // Map from raw light id to raw light info
376 std::unordered_map<int32_t, RawLightInfo> rawInfos;
377 for (const auto& rawId : rawLightIds) {
378 std::optional<RawLightInfo> rawInfo = getDeviceContext().getRawLightInfo(rawId);
379 if (!rawInfo.has_value()) {
380 continue;
381 }
382 rawInfos.insert_or_assign(rawId, rawInfo.value());
383 // Check if this is a group LEDs for player ID
384 std::regex lightPattern("([a-z]+)([0-9]+)");
385 std::smatch results;
386 if (std::regex_match(rawInfo->name, results, lightPattern)) {
387 std::string commonName = results[1].str();
388 int32_t playerId = std::stoi(results[2]);
389 if (playerIdLightIds.empty()) {
390 playerIdName = commonName;
391 playerIdLightIds.insert_or_assign(playerId, rawId);
392 } else {
393 // Make sure the player ID leds have common string name
394 if (playerIdName.compare(commonName) == 0 &&
395 playerIdLightIds.find(playerId) == playerIdLightIds.end()) {
396 playerIdLightIds.insert_or_assign(playerId, rawId);
397 }
398 }
399 }
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000400 // Check if this is a Keyboard backlight
401 if (rawInfo->flags.test(InputLightClass::KEYBOARD_BACKLIGHT)) {
402 keyboardBacklightIds.insert(rawId);
403 }
Chris Yee2b1e5c2021-03-10 22:45:12 -0800404 // Check if this is an LED of RGB light
405 if (rawInfo->flags.test(InputLightClass::RED)) {
406 hasRedLed = true;
407 rawRgbIds.emplace(LightColor::RED, rawId);
408 }
409 if (rawInfo->flags.test(InputLightClass::GREEN)) {
410 hasGreenLed = true;
411 rawRgbIds.emplace(LightColor::GREEN, rawId);
412 }
413 if (rawInfo->flags.test(InputLightClass::BLUE)) {
414 hasBlueLed = true;
415 rawRgbIds.emplace(LightColor::BLUE, rawId);
416 }
417 if (rawInfo->flags.test(InputLightClass::GLOBAL)) {
418 rawGlobalId = rawId;
419 }
420 if (DEBUG_LIGHT_DETAILS) {
421 ALOGD("Light rawId %d name %s max %d flags %s \n", rawInfo->id, rawInfo->name.c_str(),
422 rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS), rawInfo->flags.string().c_str());
423 }
424 }
425
426 // Construct a player ID light
427 if (playerIdLightIds.size() > 1) {
428 std::unique_ptr<Light> light =
429 std::make_unique<PlayerIdLight>(getDeviceContext(), playerIdName, ++mNextId,
430 playerIdLightIds);
431 mLights.insert_or_assign(light->id, std::move(light));
432 // Remove these raw lights from raw light info as they've been used to compose a
Chris Ye85758332021-05-16 23:05:17 -0700433 // Player ID light, so we do not expose these raw lights as mono lights.
Chris Yee2b1e5c2021-03-10 22:45:12 -0800434 for (const auto& [playerId, rawId] : playerIdLightIds) {
435 rawInfos.erase(rawId);
436 }
437 }
438 // Construct a RGB light for composed RGB light
439 if (hasRedLed && hasGreenLed && hasBlueLed) {
440 if (DEBUG_LIGHT_DETAILS) {
441 ALOGD("Rgb light ids [%d, %d, %d] \n", rawRgbIds.at(LightColor::RED),
442 rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
443 }
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000444 bool isKeyboardBacklight = keyboardBacklightIds.find(rawRgbIds.at(LightColor::RED)) !=
445 keyboardBacklightIds.end() &&
446 keyboardBacklightIds.find(rawRgbIds.at(LightColor::GREEN)) !=
447 keyboardBacklightIds.end() &&
448 keyboardBacklightIds.find(rawRgbIds.at(LightColor::BLUE)) !=
449 keyboardBacklightIds.end() &&
450 (!rawGlobalId.has_value() ||
451 keyboardBacklightIds.find(rawGlobalId.value()) != keyboardBacklightIds.end());
452
Chris Yee2b1e5c2021-03-10 22:45:12 -0800453 std::unique_ptr<Light> light =
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000454 std::make_unique<RgbLight>(getDeviceContext(), ++mNextId,
455 isKeyboardBacklight
456 ? InputDeviceLightType::KEYBOARD_BACKLIGHT
457 : InputDeviceLightType::INPUT,
458 rawRgbIds, rawGlobalId);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800459 mLights.insert_or_assign(light->id, std::move(light));
460 // Remove from raw light info as they've been composed a RBG light.
461 rawInfos.erase(rawRgbIds.at(LightColor::RED));
462 rawInfos.erase(rawRgbIds.at(LightColor::GREEN));
463 rawInfos.erase(rawRgbIds.at(LightColor::BLUE));
464 if (rawGlobalId.has_value()) {
465 rawInfos.erase(rawGlobalId.value());
466 }
467 }
468
469 // Check the rest of raw light infos
470 for (const auto& [rawId, rawInfo] : rawInfos) {
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000471 InputDeviceLightType type = keyboardBacklightIds.find(rawId) != keyboardBacklightIds.end()
472 ? InputDeviceLightType::KEYBOARD_BACKLIGHT
473 : InputDeviceLightType::INPUT;
474
Chris Yee2b1e5c2021-03-10 22:45:12 -0800475 // If the node is multi-color led, construct a MULTI_COLOR light
476 if (rawInfo.flags.test(InputLightClass::MULTI_INDEX) &&
477 rawInfo.flags.test(InputLightClass::MULTI_INTENSITY)) {
478 if (DEBUG_LIGHT_DETAILS) {
479 ALOGD("Multicolor light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
480 }
481 std::unique_ptr<Light> light =
482 std::make_unique<MultiColorLight>(getDeviceContext(), rawInfo.name, ++mNextId,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000483 type, rawInfo.id);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800484 mLights.insert_or_assign(light->id, std::move(light));
485 continue;
486 }
Chris Ye85758332021-05-16 23:05:17 -0700487 // Construct a Mono LED light
Chris Yee2b1e5c2021-03-10 22:45:12 -0800488 if (DEBUG_LIGHT_DETAILS) {
Chris Ye85758332021-05-16 23:05:17 -0700489 ALOGD("Mono light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
Chris Yee2b1e5c2021-03-10 22:45:12 -0800490 }
Chris Ye85758332021-05-16 23:05:17 -0700491 std::unique_ptr<Light> light = std::make_unique<MonoLight>(getDeviceContext(), rawInfo.name,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +0000492 ++mNextId, type, rawInfo.id);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800493
494 mLights.insert_or_assign(light->id, std::move(light));
495 }
496}
497
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700498std::optional<int32_t> PeripheralController::getBatteryCapacity(int batteryId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800499 return getDeviceContext().getBatteryCapacity(batteryId);
500}
501
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700502std::optional<int32_t> PeripheralController::getBatteryStatus(int batteryId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800503 return getDeviceContext().getBatteryStatus(batteryId);
504}
505
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700506bool PeripheralController::setLightColor(int32_t lightId, int32_t color) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800507 auto it = mLights.find(lightId);
508 if (it == mLights.end()) {
509 return false;
510 }
511 auto& light = it->second;
512 if (DEBUG_LIGHT_DETAILS) {
513 ALOGD("setLightColor lightId %d type %s color 0x%x", lightId,
Dominik Laskowski75788452021-02-09 18:51:25 -0800514 ftl::enum_string(light->type).c_str(), color);
Chris Yee2b1e5c2021-03-10 22:45:12 -0800515 }
516 return light->setLightColor(color);
517}
518
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700519std::optional<int32_t> PeripheralController::getLightColor(int32_t lightId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800520 auto it = mLights.find(lightId);
521 if (it == mLights.end()) {
522 return std::nullopt;
523 }
524 auto& light = it->second;
525 std::optional<int32_t> color = light->getLightColor();
526 if (DEBUG_LIGHT_DETAILS) {
527 ALOGD("getLightColor lightId %d type %s color 0x%x", lightId,
Dominik Laskowski75788452021-02-09 18:51:25 -0800528 ftl::enum_string(light->type).c_str(), color.value_or(0));
Chris Yee2b1e5c2021-03-10 22:45:12 -0800529 }
530 return color;
531}
532
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700533bool PeripheralController::setLightPlayerId(int32_t lightId, int32_t playerId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800534 auto it = mLights.find(lightId);
535 if (it == mLights.end()) {
536 return false;
537 }
538 auto& light = it->second;
539 return light->setLightPlayerId(playerId);
540}
541
Chris Ye1dd2e5c2021-04-04 23:12:41 -0700542std::optional<int32_t> PeripheralController::getLightPlayerId(int32_t lightId) {
Chris Yee2b1e5c2021-03-10 22:45:12 -0800543 auto it = mLights.find(lightId);
544 if (it == mLights.end()) {
545 return std::nullopt;
546 }
547 auto& light = it->second;
548 return light->getLightPlayerId();
549}
550
Andy Chenf9f1a022022-08-29 20:07:10 -0400551int32_t PeripheralController::getEventHubId() const {
552 return getDeviceContext().getEventHubId();
553}
554
Chris Yee2b1e5c2021-03-10 22:45:12 -0800555} // namespace android