1 /* 2 * Copyright (C) 2023 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 //! This module implements the ILights AIDL interface. 17 18 use rustutils::system_properties; 19 use std::collections::HashMap; 20 use std::sync::Mutex; 21 22 use log::info; 23 24 use android_hardware_light::aidl::android::hardware::light::{ 25 HwLight::HwLight, HwLightState::HwLightState, ILights::ILights, LightType::LightType, 26 }; 27 28 use binder::{ExceptionCode, Interface, Status}; 29 30 mod lights_vsock_server; 31 use lights_vsock_server::{SerializableLight, VsockServer}; 32 33 struct Light { 34 hw_light: HwLight, 35 state: HwLightState, 36 } 37 38 const NUM_DEFAULT_LIGHTS: i32 = 1; 39 40 /// Defined so we can implement the ILights AIDL interface. 41 pub struct LightsService { 42 lights: Mutex<HashMap<i32, Light>>, 43 // TODO(b/295543722): Move to a virtio_console transport instead. 44 vsock_server: VsockServer, 45 } 46 47 impl Interface for LightsService {} 48 49 impl LightsService { new(hw_lights: impl IntoIterator<Item = HwLight>) -> Self50 fn new(hw_lights: impl IntoIterator<Item = HwLight>) -> Self { 51 let mut lights_map = HashMap::new(); 52 53 for hw_light in hw_lights { 54 lights_map.insert(hw_light.id, Light { hw_light, state: Default::default() }); 55 } 56 57 let lights_server_port: u32 = system_properties::read("ro.boot.vsock_lights_port") 58 .unwrap_or(None) 59 .unwrap_or("0".to_string()) 60 .parse() 61 .unwrap(); 62 63 // TODO(b/297094647): Add an on_client_connected callback and share it with the 64 // vsock_server through a Weak reference. 65 Self { 66 lights: Mutex::new(lights_map), 67 vsock_server: VsockServer::new(lights_server_port).unwrap(), 68 } 69 } 70 } 71 72 impl Default for LightsService { default() -> Self73 fn default() -> Self { 74 let id_mapping_closure = 75 |light_id| HwLight { id: light_id, ordinal: light_id, r#type: LightType::BATTERY }; 76 77 Self::new((1..=NUM_DEFAULT_LIGHTS).map(id_mapping_closure)) 78 } 79 } 80 81 impl ILights for LightsService { setLightState(&self, id: i32, state: &HwLightState) -> binder::Result<()>82 fn setLightState(&self, id: i32, state: &HwLightState) -> binder::Result<()> { 83 info!("Lights setting state for id={} to color {:x}", id, state.color); 84 85 if let Some(light) = self.lights.lock().unwrap().get_mut(&id) { 86 light.state = *state; 87 88 let ser_light = SerializableLight::new( 89 light.hw_light.id as u32, 90 light.state.color as u32, 91 match light.hw_light.r#type { 92 LightType::BACKLIGHT => 0, 93 LightType::KEYBOARD => 1, 94 LightType::BUTTONS => 2, 95 LightType::BATTERY => 3, 96 LightType::NOTIFICATIONS => 4, 97 LightType::ATTENTION => 5, 98 LightType::BLUETOOTH => 6, 99 LightType::WIFI => 7, 100 LightType::MICROPHONE => 8, 101 LightType::CAMERA => 9, 102 _ => todo!(), 103 }, 104 ); 105 106 self.vsock_server.send_lights_state(vec![ser_light]); 107 108 Ok(()) 109 } else { 110 Err(Status::new_exception(ExceptionCode::UNSUPPORTED_OPERATION, None)) 111 } 112 } 113 getLights(&self) -> binder::Result<Vec<HwLight>>114 fn getLights(&self) -> binder::Result<Vec<HwLight>> { 115 info!("Lights reporting supported lights"); 116 Ok(self.lights.lock().unwrap().values().map(|light| light.hw_light).collect()) 117 } 118 } 119