Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created April 1, 2021 19:02
Show Gist options
  • Save rust-play/6d27a91c1c8e402a181ddc3d47bca747 to your computer and use it in GitHub Desktop.
Save rust-play/6d27a91c1c8e402a181ddc3d47bca747 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use anyhow::{Context as _, Error};
use fuchsia_component::server::ServiceObjLocal;
use futures::lock::Mutex;
use futures::prelude::*;
use std::pin::Pin;
use std::sync::Arc;
// Include Brightness Control FIDL bindings
use backlight::Backlight;
use control::{Control, ControlTrait, WatcherAdjustmentResponder,
WatcherAutoResponder, WatcherCurrentResponder};
use fidl_fuchsia_ui_brightness::ControlRequestStream;
use fuchsia_async::{self as fasync};
use fuchsia_component::server::ServiceFs;
use fuchsia_syslog::{self, fx_log_err, fx_log_info};
use futures::channel::mpsc::UnboundedReceiver;
use futures::future::{AbortHandle, Abortable};
use sender_channel::SenderChannel;
use sensor::Sensor;
use watch_handler::WatchHandler;
mod backlight {
// TODO(kpt) Writes FIDL client unit test for this.
use anyhow::{Context as _, Error};
use async_trait::async_trait;
use fidl_fuchsia_hardware_backlight::{DeviceMarker as BacklightMarker,
DeviceProxy as BacklightProxy, State
as BacklightCommand};
use fuchsia_syslog::fx_log_info;
const MINIMUM_BRIGHTNESS: f64 = 0.0004;
fn open_backlight() -> Result<BacklightProxy, Error> {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Opening backlight"],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
let (proxy, server) =
fidl::endpoints::create_proxy::<BacklightMarker>().context("Failed to create backlight proxy")?;
fdio::service_connect("/dev/class/backlight/000",
server.into_channel()).context("Failed to connect built-in service")?;
Ok(proxy)
}
pub struct Backlight {
proxy: BacklightProxy,
}
impl Backlight {
pub async fn new() -> Result<Backlight, Error> {
let proxy = open_backlight()?;
Ok(Backlight{proxy,})
}
pub async fn get_max_absolute_brightness(&self)
-> Result<f64, Error> {
let connection_result =
self.proxy.get_max_absolute_brightness().await;
let connection =
connection_result.map_err(|e|
::anyhow::private::new_adhoc({
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Didn\'t connect correctly, got err "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}));
res
}))?;
let max_brightness: f64 =
connection.map_err(|e|
{
::anyhow::private::new_adhoc({
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Didn\'t get the max_brightness back, got err "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}));
res
})
})?;
Ok(max_brightness)
}
async fn get(&self) -> Result<f64, Error> {
let result = self.proxy.get_state_normalized().await?;
let backlight_info =
result.map_err(|e|
::anyhow::private::new_adhoc({
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Failed to get state: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Debug::fmt)],
}));
res
}))?;
if !(backlight_info.brightness >= 0.0) {
::core::panicking::panic("assertion failed: backlight_info.brightness >= 0.0")
};
if !(backlight_info.brightness <= 1.0) {
::core::panicking::panic("assertion failed: backlight_info.brightness <= 1.0")
};
Ok(if backlight_info.backlight_on {
backlight_info.brightness
} else { 0.0 })
}
fn set(&mut self, value: f64) -> Result<(), Error> {
let regulated_value =
num_traits::clamp(value, MINIMUM_BRIGHTNESS, 1.0);
let _result =
self.proxy.set_state_normalized(&mut BacklightCommand{backlight_on:
value
>
0.0,
brightness:
regulated_value,});
Ok(())
}
}
pub trait BacklightControl: Send {
#[must_use]
fn get_brightness<'life0, 'async_trait>(&'life0 self)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
Result<f64,
Error>> +
::core::marker::Send + 'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
fn set_brightness(&mut self, value: f64)
-> Result<(), Error>;
#[must_use]
fn get_max_absolute_brightness<'life0, 'async_trait>(&'life0 self)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
Result<f64,
Error>> +
::core::marker::Send + 'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
}
impl BacklightControl for Backlight {
fn get_brightness<'life0, 'async_trait>(&'life0 self)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
Result<f64,
Error>> +
::core::marker::Send + 'async_trait>> where
'life0: 'async_trait, Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __get_brightness(_self: &Backlight)
-> Result<f64, Error> {
_self.get().await
}
Box::pin(__get_brightness::<>(self))
}
fn set_brightness(&mut self, value: f64) -> Result<(), Error> {
self.set(value)
}
fn get_max_absolute_brightness<'life0, 'async_trait>(&'life0 self)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
Result<f64,
Error>> +
::core::marker::Send + 'async_trait>> where
'life0: 'async_trait, Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __get_max_absolute_brightness(_self: &Backlight)
-> Result<f64, Error> {
_self.get_max_absolute_brightness().await
}
Box::pin(__get_max_absolute_brightness::<>(self))
}
}
}
mod control {
use crate::backlight::BacklightControl;
use crate::sender_channel::SenderChannel;
use crate::sensor::SensorControl;
use async_trait::async_trait;
use std::cmp;
use std::sync::Arc;
use anyhow::{format_err, Error};
use fidl_fuchsia_ui_brightness::{ControlRequest as
BrightnessControlRequest,
ControlWatchAutoBrightnessAdjustmentResponder,
ControlWatchAutoBrightnessResponder,
ControlWatchCurrentBrightnessResponder};
use fuchsia_async::{self as fasync, DurationExt};
use fuchsia_syslog::{self, fx_log_err, fx_log_info};
use fuchsia_zircon::sys::ZX_ERR_NOT_SUPPORTED;
use fuchsia_zircon::{Duration, DurationNum};
use futures::channel::mpsc::UnboundedSender;
use futures::future::{AbortHandle, Abortable};
use futures::lock::Mutex;
use futures::prelude::*;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use serde_json;
use splines::{Interpolation, Key, Spline};
use std::{fs, io};
use watch_handler::{Sender, WatchHandler};
const SLOW_SCAN_TIMEOUT_MS: i64 = 2000;
const QUICK_SCAN_TIMEOUT_MS: i64 = 100;
const LARGE_CHANGE_THRESHOLD_NITS: i32 = 0.016 as i32;
const AUTO_MINIMUM_BRIGHTNESS: f32 = 0.004;
const BRIGHTNESS_USER_MULTIPLIER_CENTER: f32 = 1.0;
const BRIGHTNESS_USER_MULTIPLIER_MAX: f32 = 8.0;
const BRIGHTNESS_USER_MULTIPLIER_MIN: f32 = 0.25;
const BRIGHTNESS_TABLE_FILE_PATH: &str = "/data/brightness_table";
const BRIGHTNESS_MINIMUM_CHANGE: f32 = 0.00001;
const BRIGHTNESS_STEP_SIZE: f32 = 0.001;
const MAX_BRIGHTNESS_STEP_TIME_MS: i64 = 100;
const BRIGHTNESS_CHANGE_DURATION_MS: i64 = 2000;
struct BrightnessPoint {
ambient_lux: f32,
display_nits: f32,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () =
{
#[allow(rust_2018_idioms, clippy :: useless_attribute)]
extern crate serde as _serde;
#[allow(unused_macros)]
macro_rules! try {
($ __expr : expr) =>
{
match $ __expr
{
_serde :: export :: Ok(__val) => __val, _serde ::
export :: Err(__err) =>
{ return _serde :: export :: Err(__err) ; }
}
}
}
#[automatically_derived]
impl _serde::Serialize for BrightnessPoint {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::export::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
match _serde::Serializer::serialize_struct(__serializer,
"BrightnessPoint",
false as
usize +
1 + 1)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"ambient_lux",
&self.ambient_lux)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"display_nits",
&self.display_nits)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () =
{
#[allow(rust_2018_idioms, clippy :: useless_attribute)]
extern crate serde as _serde;
#[allow(unused_macros)]
macro_rules! try {
($ __expr : expr) =>
{
match $ __expr
{
_serde :: export :: Ok(__val) => __val, _serde ::
export :: Err(__err) =>
{ return _serde :: export :: Err(__err) ; }
}
}
}
#[automatically_derived]
impl <'de> _serde::Deserialize<'de> for BrightnessPoint {
fn deserialize<__D>(__deserializer: __D)
-> _serde::export::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
enum __Field { __field0, __field1, __ignore, }
struct __FieldVisitor;
impl <'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter:
&mut _serde::export::Formatter)
-> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::export::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
_ =>
_serde::export::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 2")),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::export::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"ambient_lux" =>
_serde::export::Ok(__Field::__field0),
"display_nits" =>
_serde::export::Ok(__Field::__field1),
_ => { _serde::export::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::export::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"ambient_lux" =>
_serde::export::Ok(__Field::__field0),
b"display_nits" =>
_serde::export::Ok(__Field::__field1),
_ => { _serde::export::Ok(__Field::__ignore) }
}
}
}
impl <'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::export::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
struct __Visitor<'de> {
marker: _serde::export::PhantomData<BrightnessPoint>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl <'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = BrightnessPoint;
fn expecting(&self,
__formatter:
&mut _serde::export::Formatter)
-> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter,
"struct BrightnessPoint")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(0usize,
&"struct BrightnessPoint with 2 elements"));
}
};
let __field1 =
match match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(1usize,
&"struct BrightnessPoint with 2 elements"));
}
};
_serde::export::Ok(BrightnessPoint{ambient_lux:
__field0,
display_nits:
__field1,})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::export::Option<f32> =
_serde::export::None;
let mut __field1: _serde::export::Option<f32> =
_serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0)
{
return _serde::export::Err(<__A::Error
as
_serde::de::Error>::duplicate_field("ambient_lux"));
}
__field0 =
_serde::export::Some(match _serde::de::MapAccess::next_value::<f32>(&mut __map)
{
_serde::export::Ok(__val)
=> __val,
_serde::export::Err(__err)
=> {
return _serde::export::Err(__err);
}
});
}
__Field::__field1 => {
if _serde::export::Option::is_some(&__field1)
{
return _serde::export::Err(<__A::Error
as
_serde::de::Error>::duplicate_field("display_nits"));
}
__field1 =
_serde::export::Some(match _serde::de::MapAccess::next_value::<f32>(&mut __map)
{
_serde::export::Ok(__val)
=> __val,
_serde::export::Err(__err)
=> {
return _serde::export::Err(__err);
}
});
}
_ => {
let _ =
match _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)
{
_serde::export::Ok(__val) =>
__val,
_serde::export::Err(__err) =>
{
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 =
match __field0 {
_serde::export::Some(__field0) =>
__field0,
_serde::export::None =>
match _serde::private::de::missing_field("ambient_lux")
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
let __field1 =
match __field1 {
_serde::export::Some(__field1) =>
__field1,
_serde::export::None =>
match _serde::private::de::missing_field("display_nits")
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
_serde::export::Ok(BrightnessPoint{ambient_lux:
__field0,
display_nits:
__field1,})
}
}
const FIELDS: &'static [&'static str] =
&["ambient_lux", "display_nits"];
_serde::Deserializer::deserialize_struct(__deserializer,
"BrightnessPoint",
FIELDS,
__Visitor{marker:
_serde::export::PhantomData::<BrightnessPoint>,
lifetime:
_serde::export::PhantomData,})
}
}
};
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for BrightnessPoint {
#[inline]
fn clone(&self) -> BrightnessPoint {
match *self {
BrightnessPoint {
ambient_lux: ref __self_0_0, display_nits: ref __self_0_1 } =>
BrightnessPoint{ambient_lux:
::core::clone::Clone::clone(&(*__self_0_0)),
display_nits:
::core::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
struct BrightnessTable {
points: Vec<BrightnessPoint>,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () =
{
#[allow(rust_2018_idioms, clippy :: useless_attribute)]
extern crate serde as _serde;
#[allow(unused_macros)]
macro_rules! try {
($ __expr : expr) =>
{
match $ __expr
{
_serde :: export :: Ok(__val) => __val, _serde ::
export :: Err(__err) =>
{ return _serde :: export :: Err(__err) ; }
}
}
}
#[automatically_derived]
impl _serde::Serialize for BrightnessTable {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::export::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
match _serde::Serializer::serialize_struct(__serializer,
"BrightnessTable",
false as
usize +
1) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"points",
&self.points)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () =
{
#[allow(rust_2018_idioms, clippy :: useless_attribute)]
extern crate serde as _serde;
#[allow(unused_macros)]
macro_rules! try {
($ __expr : expr) =>
{
match $ __expr
{
_serde :: export :: Ok(__val) => __val, _serde ::
export :: Err(__err) =>
{ return _serde :: export :: Err(__err) ; }
}
}
}
#[automatically_derived]
impl <'de> _serde::Deserialize<'de> for BrightnessTable {
fn deserialize<__D>(__deserializer: __D)
-> _serde::export::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
enum __Field { __field0, __ignore, }
struct __FieldVisitor;
impl <'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter:
&mut _serde::export::Formatter)
-> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::export::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ =>
_serde::export::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1")),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::export::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"points" =>
_serde::export::Ok(__Field::__field0),
_ => { _serde::export::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::export::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"points" =>
_serde::export::Ok(__Field::__field0),
_ => { _serde::export::Ok(__Field::__ignore) }
}
}
}
impl <'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::export::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
struct __Visitor<'de> {
marker: _serde::export::PhantomData<BrightnessTable>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl <'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = BrightnessTable;
fn expecting(&self,
__formatter:
&mut _serde::export::Formatter)
-> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter,
"struct BrightnessTable")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match match _serde::de::SeqAccess::next_element::<Vec<BrightnessPoint>>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(0usize,
&"struct BrightnessTable with 1 element"));
}
};
_serde::export::Ok(BrightnessTable{points:
__field0,})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0:
_serde::export::Option<Vec<BrightnessPoint>> =
_serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0)
{
return _serde::export::Err(<__A::Error
as
_serde::de::Error>::duplicate_field("points"));
}
__field0 =
_serde::export::Some(match _serde::de::MapAccess::next_value::<Vec<BrightnessPoint>>(&mut __map)
{
_serde::export::Ok(__val)
=> __val,
_serde::export::Err(__err)
=> {
return _serde::export::Err(__err);
}
});
}
_ => {
let _ =
match _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)
{
_serde::export::Ok(__val) =>
__val,
_serde::export::Err(__err) =>
{
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 =
match __field0 {
_serde::export::Some(__field0) =>
__field0,
_serde::export::None =>
match _serde::private::de::missing_field("points")
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
_serde::export::Ok(BrightnessTable{points:
__field0,})
}
}
const FIELDS: &'static [&'static str] = &["points"];
_serde::Deserializer::deserialize_struct(__deserializer,
"BrightnessTable",
FIELDS,
__Visitor{marker:
_serde::export::PhantomData::<BrightnessTable>,
lifetime:
_serde::export::PhantomData,})
}
}
};
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for BrightnessTable {
#[inline]
fn clone(&self) -> BrightnessTable {
match *self {
BrightnessTable { points: ref __self_0_0 } =>
BrightnessTable{points:
::core::clone::Clone::clone(&(*__self_0_0)),},
}
}
}
impl From<fidl_fuchsia_ui_brightness::BrightnessPoint> for BrightnessPoint
{
fn from(brightness_point: fidl_fuchsia_ui_brightness::BrightnessPoint)
-> Self {
return BrightnessPoint{ambient_lux: brightness_point.ambient_lux,
display_nits:
brightness_point.display_nits,};
}
}
impl From<fidl_fuchsia_ui_brightness::BrightnessTable> for BrightnessTable
{
fn from(brightness_table: fidl_fuchsia_ui_brightness::BrightnessTable)
-> Self {
let fidl_fuchsia_ui_brightness::BrightnessTable { points } =
brightness_table;
return BrightnessTable{points:
points.into_iter().map(|p|
p.into()).collect(),};
}
}
#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
struct BRIGHTNESS_TABLE {
__private_field: (),
}
#[doc(hidden)]
static BRIGHTNESS_TABLE: BRIGHTNESS_TABLE =
BRIGHTNESS_TABLE{__private_field: (),};
impl ::lazy_static::__Deref for BRIGHTNESS_TABLE {
type Target = Arc<Mutex<BrightnessTable>>;
fn deref(&self) -> &Arc<Mutex<BrightnessTable>> {
#[inline(always)]
fn __static_ref_initialize() -> Arc<Mutex<BrightnessTable>> {
{
let mut lux_to_nits = Vec::new();
lux_to_nits.push(BrightnessPoint{ambient_lux: 0.,
display_nits: 0.,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 10.,
display_nits: 3.33,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 30.,
display_nits: 8.7,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 60.,
display_nits: 18.27,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 100.,
display_nits: 32.785,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 150.,
display_nits: 36.82,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 210.,
display_nits: 75.0,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 250.,
display_nits: 124.16,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 300.,
display_nits: 162.96,});
lux_to_nits.push(BrightnessPoint{ambient_lux: 340.,
display_nits: 300.,});
Arc::new(Mutex::new(BrightnessTable{points:
lux_to_nits,}))
}
}
#[inline(always)]
fn __stability() -> &'static Arc<Mutex<BrightnessTable>> {
static LAZY:
::lazy_static::lazy::Lazy<Arc<Mutex<BrightnessTable>>> =
::lazy_static::lazy::Lazy::INIT;
LAZY.get(__static_ref_initialize)
}
__stability()
}
}
impl ::lazy_static::LazyStatic for BRIGHTNESS_TABLE {
fn initialize(lazy: &Self) { let _ = &**lazy; }
}
#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
struct AUTO_BRIGHTNESS_ADJUSTMENT {
__private_field: (),
}
#[doc(hidden)]
static AUTO_BRIGHTNESS_ADJUSTMENT: AUTO_BRIGHTNESS_ADJUSTMENT =
AUTO_BRIGHTNESS_ADJUSTMENT{__private_field: (),};
impl ::lazy_static::__Deref for AUTO_BRIGHTNESS_ADJUSTMENT {
type Target = Arc<Mutex<f32>>;
fn deref(&self) -> &Arc<Mutex<f32>> {
#[inline(always)]
fn __static_ref_initialize() -> Arc<Mutex<f32>> {
Arc::new(Mutex::new(1.0))
}
#[inline(always)]
fn __stability() -> &'static Arc<Mutex<f32>> {
static LAZY: ::lazy_static::lazy::Lazy<Arc<Mutex<f32>>> =
::lazy_static::lazy::Lazy::INIT;
LAZY.get(__static_ref_initialize)
}
__stability()
}
}
impl ::lazy_static::LazyStatic for AUTO_BRIGHTNESS_ADJUSTMENT {
fn initialize(lazy: &Self) { let _ = &**lazy; }
}
#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
struct GET_BRIGHTNESS_FAILED_FIRST {
__private_field: (),
}
#[doc(hidden)]
static GET_BRIGHTNESS_FAILED_FIRST: GET_BRIGHTNESS_FAILED_FIRST =
GET_BRIGHTNESS_FAILED_FIRST{__private_field: (),};
impl ::lazy_static::__Deref for GET_BRIGHTNESS_FAILED_FIRST {
type Target = Arc<Mutex<bool>>;
fn deref(&self) -> &Arc<Mutex<bool>> {
#[inline(always)]
fn __static_ref_initialize() -> Arc<Mutex<bool>> {
Arc::new(Mutex::new(true))
}
#[inline(always)]
fn __stability() -> &'static Arc<Mutex<bool>> {
static LAZY: ::lazy_static::lazy::Lazy<Arc<Mutex<bool>>> =
::lazy_static::lazy::Lazy::INIT;
LAZY.get(__static_ref_initialize)
}
__stability()
}
}
impl ::lazy_static::LazyStatic for GET_BRIGHTNESS_FAILED_FIRST {
fn initialize(lazy: &Self) { let _ = &**lazy; }
}
#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
struct LAST_SET_BRIGHTNESS {
__private_field: (),
}
#[doc(hidden)]
static LAST_SET_BRIGHTNESS: LAST_SET_BRIGHTNESS =
LAST_SET_BRIGHTNESS{__private_field: (),};
impl ::lazy_static::__Deref for LAST_SET_BRIGHTNESS {
type Target = Arc<Mutex<f32>>;
fn deref(&self) -> &Arc<Mutex<f32>> {
#[inline(always)]
fn __static_ref_initialize() -> Arc<Mutex<f32>> {
Arc::new(Mutex::new(1.0))
}
#[inline(always)]
fn __stability() -> &'static Arc<Mutex<f32>> {
static LAZY: ::lazy_static::lazy::Lazy<Arc<Mutex<f32>>> =
::lazy_static::lazy::Lazy::INIT;
LAZY.get(__static_ref_initialize)
}
__stability()
}
}
impl ::lazy_static::LazyStatic for LAST_SET_BRIGHTNESS {
fn initialize(lazy: &Self) { let _ = &**lazy; }
}
#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
struct BRIGHTNESS_CHANGE_DURATION {
__private_field: (),
}
#[doc(hidden)]
static BRIGHTNESS_CHANGE_DURATION: BRIGHTNESS_CHANGE_DURATION =
BRIGHTNESS_CHANGE_DURATION{__private_field: (),};
impl ::lazy_static::__Deref for BRIGHTNESS_CHANGE_DURATION {
type Target = Arc<Mutex<Duration>>;
fn deref(&self) -> &Arc<Mutex<Duration>> {
#[inline(always)]
fn __static_ref_initialize() -> Arc<Mutex<Duration>> {
Arc::new(Mutex::new(BRIGHTNESS_CHANGE_DURATION_MS.millis()))
}
#[inline(always)]
fn __stability() -> &'static Arc<Mutex<Duration>> {
static LAZY: ::lazy_static::lazy::Lazy<Arc<Mutex<Duration>>> =
::lazy_static::lazy::Lazy::INIT;
LAZY.get(__static_ref_initialize)
}
__stability()
}
}
impl ::lazy_static::LazyStatic for BRIGHTNESS_CHANGE_DURATION {
fn initialize(lazy: &Self) { let _ = &**lazy; }
}
pub struct WatcherCurrentResponder {
watcher_current_responder: ControlWatchCurrentBrightnessResponder,
}
impl Sender<f32> for WatcherCurrentResponder {
fn send_response(self, data: f32) {
if let Err(e) = self.watcher_current_responder.send(data) {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&114u32,
&::core::fmt::Arguments::new_v1(&["Failed to reply to WatchCurrentBrightness: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
}
}
}
pub struct WatcherAutoResponder {
watcher_auto_responder: ControlWatchAutoBrightnessResponder,
}
impl Sender<bool> for WatcherAutoResponder {
fn send_response(self, data: bool) {
if let Err(e) = self.watcher_auto_responder.send(data) {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&126u32,
&::core::fmt::Arguments::new_v1(&["Failed to reply to WatchAutoBrightness: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
}
}
}
pub struct WatcherAdjustmentResponder {
watcher_adjustment_responder: ControlWatchAutoBrightnessAdjustmentResponder,
}
impl Sender<f32> for WatcherAdjustmentResponder {
fn send_response(self, data: f32) {
if let Err(e) = self.watcher_adjustment_responder.send(data) {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&138u32,
&::core::fmt::Arguments::new_v1(&["Failed to reply to WatchAutoBrightnessAdjustment: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
}
}
}
pub struct Control {
sensor: Arc<Mutex<dyn SensorControl>>,
backlight: Arc<Mutex<dyn BacklightControl>>,
set_brightness_abort_handle: Arc<Mutex<Option<AbortHandle>>>,
auto_brightness_abort_handle: Option<AbortHandle>,
spline: Spline<f32, f32>,
current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
auto_sender_channel: Arc<Mutex<SenderChannel<bool>>>,
adjustment_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
}
impl Control {
pub async fn new(sensor: Arc<Mutex<dyn SensorControl>>,
backlight: Arc<Mutex<dyn BacklightControl>>,
current_sender_channel:
Arc<Mutex<SenderChannel<f32>>>,
auto_sender_channel: Arc<Mutex<SenderChannel<bool>>>,
adjustment_sender_channel:
Arc<Mutex<SenderChannel<f32>>>) -> Control {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["New Control class"],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
let set_brightness_abort_handle =
Arc::new(Mutex::new(None::<AbortHandle>));
let default_table_points = &*BRIGHTNESS_TABLE.lock().await.points;
let brightness_table =
read_brightness_table_file(BRIGHTNESS_TABLE_FILE_PATH).unwrap_or_else(|e|
{
{
let lvl =
::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&168u32,
&::core::fmt::Arguments::new_v1(&["Error occurred when trying to read existing settings: ",
", using default table instead."],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl,
"");
};
;
BrightnessTable{points:
default_table_points.to_vec(),}
});
let spline = generate_spline(&brightness_table);
let auto_brightness_abort_handle = None::<AbortHandle>;
let mut result =
Control{backlight,
sensor,
set_brightness_abort_handle,
auto_brightness_abort_handle,
spline,
current_sender_channel,
auto_sender_channel,
adjustment_sender_channel,};
result.start_auto_brightness_task();
result
}
pub async fn handle_request(&mut self,
request: BrightnessControlRequest,
watch_current_handler:
Arc<Mutex<WatchHandler<f32,
WatcherCurrentResponder>>>,
watch_auto_handler:
Arc<Mutex<WatchHandler<bool,
WatcherAutoResponder>>>,
watch_adjustment_handler:
Arc<Mutex<WatchHandler<f32,
WatcherAdjustmentResponder>>>) {
match request {
BrightnessControlRequest::SetAutoBrightness {
control_handle: _ } => {
self.set_auto_brightness().await;
}
BrightnessControlRequest::WatchAutoBrightness { responder } =>
{
let watch_auto_result =
self.watch_auto_brightness(watch_auto_handler,
responder).await;
match watch_auto_result {
Ok(_v) => { }
Err(e) => {
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&208u32,
&::core::fmt::Arguments::new_v1(&["Watch auto brightness failed due to err ",
"."],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
}
}
}
BrightnessControlRequest::SetManualBrightness {
value, control_handle: _ } => {
let value = num_traits::clamp(value, 0.0, 1.0);
self.set_manual_brightness(value).await;
}
BrightnessControlRequest::SetManualBrightnessSmooth {
value, duration, control_handle: _ } => {
self.set_manual_brightness_smooth(value, duration).await;
}
BrightnessControlRequest::WatchCurrentBrightness { responder }
=> {
let watch_current_result =
self.watch_current_brightness(watch_current_handler,
responder).await;
match watch_current_result {
Ok(_v) => { }
Err(e) => {
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&227u32,
&::core::fmt::Arguments::new_v1(&["Watch current brightness failed due to err ",
"."],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
}
}
}
BrightnessControlRequest::SetBrightnessTable {
table, control_handle: _ } => {
let result =
self.check_brightness_table_and_set_new_curve(&table.into()).await;
match result {
Ok(_v) => {
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Brightness table is valid and set"],
&match ()
{
()
=>
[],
}),
lvl, "");
}
Err(e) => {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&236u32,
&::core::fmt::Arguments::new_v1(&["Brightness table is not valid because "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
}
}
}
BrightnessControlRequest::SetAutoBrightnessAdjustment {
adjustment, control_handle: _ } => {
self.scale_new_adjustment(adjustment).await;
}
BrightnessControlRequest::WatchAutoBrightnessAdjustment {
responder } => {
let watch_adjustment_result =
self.watch_auto_brightness_adjustment(watch_adjustment_handler,
responder).await;
match watch_adjustment_result {
Ok(_v) => { }
Err(e) => {
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&253u32,
&::core::fmt::Arguments::new_v1(&["Watch adjustment failed due to err ",
"."],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
}
}
}
BrightnessControlRequest::GetMaxAbsoluteBrightness { responder
} => {
let result = self.get_max_absolute_brightness();
match result.await {
Ok(value) => {
if let Err(e) = responder.send(&mut Ok(value)) {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&261u32,
&::core::fmt::Arguments::new_v1(&["Failed to reply to GetMaxAbsoluteBrightness: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
}
}
Err(e) => {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&265u32,
&::core::fmt::Arguments::new_v1(&["Failed to get max absolute brightness: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
if let Err(e) =
responder.send(&mut Err(ZX_ERR_NOT_SUPPORTED))
{
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&268u32,
&::core::fmt::Arguments::new_v1(&["Failed to reply to GetMaxAbsoluteBrightness: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
}
}
}
}
}
}
pub async fn add_current_sender_channel(&mut self,
sender:
UnboundedSender<f32>) {
self.current_sender_channel.lock().await.add_sender_channel(sender).await;
}
pub async fn add_auto_sender_channel(&mut self,
sender: UnboundedSender<bool>) {
self.auto_sender_channel.lock().await.add_sender_channel(sender).await;
}
pub async fn add_adjustment_sender_channel(&mut self,
sender:
UnboundedSender<f32>) {
self.adjustment_sender_channel.lock().await.add_sender_channel(sender).await;
}
pub fn get_backlight_and_auto_brightness_on(&mut self)
-> (Arc<Mutex<dyn BacklightControl>>, bool) {
(self.backlight.clone(),
self.auto_brightness_abort_handle.is_some())
}
async fn set_auto_brightness(&mut self) {
if self.auto_brightness_abort_handle.is_none() {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Auto-brightness turned on"],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
self.start_auto_brightness_task();
self.auto_sender_channel.lock().await.send_value(self.auto_brightness_abort_handle.is_some());
}
}
async fn watch_auto_brightness(&mut self,
watch_auto_handler:
Arc<Mutex<WatchHandler<bool,
WatcherAutoResponder>>>,
responder:
ControlWatchAutoBrightnessResponder)
-> Result<(), Error> {
let mut hanging_get_lock = watch_auto_handler.lock().await;
hanging_get_lock.watch(WatcherAutoResponder{watcher_auto_responder:
responder,})?;
Ok(())
}
fn start_auto_brightness_task(&mut self) {
if let Some(handle) = &self.auto_brightness_abort_handle.take() {
handle.abort();
}
let backlight = self.backlight.clone();
let sensor = self.sensor.clone();
let set_brightness_abort_handle =
self.set_brightness_abort_handle.clone();
let current_sender_channel = self.current_sender_channel.clone();
let spline = self.spline.clone();
let (abort_handle, abort_registration) = AbortHandle::new_pair();
fasync::Task::spawn(Abortable::new(async move
{
let backlight =
backlight.clone();
let max_brightness =
{
let backlight =
backlight.clone();
let backlight =
backlight.lock().await;
let max_result =
backlight.get_max_absolute_brightness();
match max_result.await
{
Ok(max_value)
=>
max_value,
Err(_e) =>
250.0,
}
};
let mut last_value:
i32 = -1;
loop {
let current_sender_channel =
current_sender_channel.clone();
let sensor =
sensor.clone();
let mut value =
read_sensor_and_get_brightness(sensor,
&spline,
max_brightness).await;
let adjustment =
*AUTO_BRIGHTNESS_ADJUSTMENT.lock().await;
value =
num_traits::clamp(value
*
adjustment,
AUTO_MINIMUM_BRIGHTNESS,
1.0);
set_brightness(value,
set_brightness_abort_handle.clone(),
backlight.clone(),
current_sender_channel).await;
let large_change =
(last_value as
i32 -
value as
i32).abs()
>
LARGE_CHANGE_THRESHOLD_NITS;
last_value =
value as i32;
let delay_timeout =
if large_change
{
QUICK_SCAN_TIMEOUT_MS
} else {
SLOW_SCAN_TIMEOUT_MS
};
fuchsia_async::Timer::new(Duration::from_millis(delay_timeout).after_now()).await;
}
},
abort_registration).unwrap_or_else(|_|
())).detach();
self.auto_brightness_abort_handle = Some(abort_handle);
}
async fn set_manual_brightness(&mut self, value: f32) {
if let Some(handle) = self.auto_brightness_abort_handle.take() {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Auto-brightness off, brightness set to "],
&match (&value,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
handle.abort();
}
self.auto_sender_channel.lock().await.send_value(false);
let current_sender_channel = self.current_sender_channel.clone();
set_brightness(value, self.set_brightness_abort_handle.clone(),
self.backlight.clone(),
current_sender_channel).await;
}
async fn set_manual_brightness_smooth(&mut self, value: f32,
duration: i64) {
let duration_nanos = Duration::from_nanos(duration);
*BRIGHTNESS_CHANGE_DURATION.lock().await =
duration_nanos.into_millis().millis();
let value = num_traits::clamp(value, 0.0, 1.0);
self.set_manual_brightness(value).await;
}
async fn watch_current_brightness(&mut self,
watch_current_handler:
Arc<Mutex<WatchHandler<f32,
WatcherCurrentResponder>>>,
responder:
ControlWatchCurrentBrightnessResponder)
-> Result<(), Error> {
let mut hanging_get_lock = watch_current_handler.lock().await;
hanging_get_lock.watch(WatcherCurrentResponder{watcher_current_responder:
responder,})?;
Ok(())
}
async fn set_brightness_curve(&mut self, table: &BrightnessTable) {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Setting new brightness curve."],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
self.spline = generate_spline(table);
self.start_auto_brightness_task();
let result =
self.store_brightness_table(table,
BRIGHTNESS_TABLE_FILE_PATH);
match result {
Ok(_v) => {
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Stored successfully"],
&match ()
{
()
=>
[],
}),
lvl, "");
}
Err(e) => {
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Didn\'t store successfully due to error "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}),
lvl, "");
}
}
}
fn store_brightness_table(&mut self, table: &BrightnessTable,
file_path: &str) -> Result<(), Error> {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Storing brightness table set."],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
let file = fs::File::create(file_path)?;
serde_json::to_writer(io::BufWriter::new(file),
&table).map_err(|e|
::anyhow::private::new_adhoc({
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Failed to write to file, ran into error: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Debug::fmt)],
}));
res
}))
}
async fn check_brightness_table_and_set_new_curve(&mut self,
table:
&BrightnessTable)
-> Result<(), Error> {
let BrightnessTable { points } = table;
if points.is_empty() {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Brightness table can not be empty, use the default table instead."],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
let BrightnessTable { points } =
&*BRIGHTNESS_TABLE.lock().await;
let brightness_table =
BrightnessTable{points: points.to_vec(),};
self.set_brightness_curve(&brightness_table).await;
return Ok(());
}
let mut last_lux = -1.0;
for brightness_point in points {
if brightness_point.ambient_lux < 0.0 ||
brightness_point.display_nits < 0.0 {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Lux or nits in this table is negative."],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
return Err({
use ::anyhow::private::kind::*;
match {
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Lux or nits in this table is negative."],
&match ()
{
()
=>
[],
}));
res
} {
error =>
(&error).anyhow_kind().new(error),
}
});
}
if brightness_point.ambient_lux > last_lux {
last_lux = brightness_point.ambient_lux;
} else {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Not increasing lux in this table."],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
return Err({
use ::anyhow::private::kind::*;
match {
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Not increasing lux in this table."],
&match ()
{
()
=>
[],
}));
res
} {
error =>
(&error).anyhow_kind().new(error),
}
});
}
}
self.set_brightness_curve(&table).await;
Ok(())
}
async fn scale_new_adjustment(&mut self, mut adjustment: f32) -> f32 {
self.adjustment_sender_channel.lock().await.send_value(adjustment);
if adjustment >= 0.0 {
adjustment =
adjustment *
(BRIGHTNESS_USER_MULTIPLIER_MAX -
BRIGHTNESS_USER_MULTIPLIER_CENTER) +
BRIGHTNESS_USER_MULTIPLIER_CENTER;
} else {
adjustment =
adjustment *
(BRIGHTNESS_USER_MULTIPLIER_CENTER -
BRIGHTNESS_USER_MULTIPLIER_MIN) +
BRIGHTNESS_USER_MULTIPLIER_CENTER;
}
*AUTO_BRIGHTNESS_ADJUSTMENT.lock().await = adjustment;
return adjustment;
}
async fn watch_auto_brightness_adjustment(&mut self,
watch_adjustment_handler:
Arc<Mutex<WatchHandler<f32,
WatcherAdjustmentResponder>>>,
responder:
ControlWatchAutoBrightnessAdjustmentResponder)
-> Result<(), Error> {
let mut hanging_get_lock = watch_adjustment_handler.lock().await;
hanging_get_lock.watch(WatcherAdjustmentResponder{watcher_adjustment_responder:
responder,})?;
Ok(())
}
async fn get_max_absolute_brightness(&mut self)
-> Result<f64, Error> {
let backlight = self.backlight.lock().await;
backlight.get_max_absolute_brightness().await
}
}
pub trait ControlTrait {
#[must_use]
fn handle_request<'life0,
'async_trait>(&'life0 mut self,
request: BrightnessControlRequest,
watch_current_handler:
Arc<Mutex<WatchHandler<f32,
WatcherCurrentResponder>>>,
watch_auto_handler:
Arc<Mutex<WatchHandler<bool,
WatcherAutoResponder>>>,
watch_adjustment_handler:
Arc<Mutex<WatchHandler<f32,
WatcherAdjustmentResponder>>>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
#[must_use]
fn add_current_sender_channel<'life0,
'async_trait>(&'life0 mut self,
sender:
UnboundedSender<f32>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
#[must_use]
fn add_auto_sender_channel<'life0,
'async_trait>(&'life0 mut self,
sender:
UnboundedSender<bool>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
#[must_use]
fn add_adjustment_sender_channel<'life0,
'async_trait>(&'life0 mut self,
sender:
UnboundedSender<f32>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
fn get_backlight_and_auto_brightness_on(&mut self)
-> (Arc<Mutex<dyn BacklightControl>>, bool);
}
impl ControlTrait for Control {
fn handle_request<'life0,
'async_trait>(&'life0 mut self,
request: BrightnessControlRequest,
watch_current_handler:
Arc<Mutex<WatchHandler<f32,
WatcherCurrentResponder>>>,
watch_auto_handler:
Arc<Mutex<WatchHandler<bool,
WatcherAutoResponder>>>,
watch_adjustment_handler:
Arc<Mutex<WatchHandler<f32,
WatcherAdjustmentResponder>>>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>> where 'life0: 'async_trait,
Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __handle_request(_self: &mut Control,
request: BrightnessControlRequest,
watch_current_handler:
Arc<Mutex<WatchHandler<f32,
WatcherCurrentResponder>>>,
watch_auto_handler:
Arc<Mutex<WatchHandler<bool,
WatcherAutoResponder>>>,
watch_adjustment_handler:
Arc<Mutex<WatchHandler<f32,
WatcherAdjustmentResponder>>>) {
_self.handle_request(request, watch_current_handler,
watch_auto_handler,
watch_adjustment_handler).await;
}
Box::pin(__handle_request::<>(self, request,
watch_current_handler,
watch_auto_handler,
watch_adjustment_handler))
}
fn add_current_sender_channel<'life0,
'async_trait>(&'life0 mut self,
sender:
UnboundedSender<f32>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>> where 'life0: 'async_trait,
Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __add_current_sender_channel(_self: &mut Control,
sender:
UnboundedSender<f32>) {
_self.add_current_sender_channel(sender).await;
}
Box::pin(__add_current_sender_channel::<>(self, sender))
}
fn add_auto_sender_channel<'life0,
'async_trait>(&'life0 mut self,
sender:
UnboundedSender<bool>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>> where 'life0: 'async_trait,
Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __add_auto_sender_channel(_self: &mut Control,
sender:
UnboundedSender<bool>) {
_self.add_auto_sender_channel(sender).await;
}
Box::pin(__add_auto_sender_channel::<>(self, sender))
}
fn add_adjustment_sender_channel<'life0,
'async_trait>(&'life0 mut self,
sender:
UnboundedSender<f32>)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> +
'async_trait>> where 'life0: 'async_trait,
Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __add_adjustment_sender_channel(_self: &mut Control,
sender:
UnboundedSender<f32>) {
_self.add_adjustment_sender_channel(sender).await;
}
Box::pin(__add_adjustment_sender_channel::<>(self, sender))
}
fn get_backlight_and_auto_brightness_on(&mut self)
-> (Arc<Mutex<dyn BacklightControl>>, bool) {
self.get_backlight_and_auto_brightness_on()
}
}
fn read_brightness_table_file(path: &str)
-> Result<BrightnessTable, Error> {
let file = fs::File::open(path)?;
let result = serde_json::from_reader(io::BufReader::new(file));
let result =
result.map_err(|e|
::anyhow::private::new_adhoc({
let res =
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&["Failed to read from file, ran into error: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Debug::fmt)],
}));
res
}));
result
}
fn generate_spline(table: &BrightnessTable) -> Spline<f32, f32> {
let BrightnessTable { points } = table;
let mut lux_to_nits_table_to_splines = Vec::new();
for brightness_point in points {
lux_to_nits_table_to_splines.push(Key::new(brightness_point.ambient_lux,
brightness_point.display_nits,
Interpolation::Linear));
}
Spline::from_iter(lux_to_nits_table_to_splines.iter().cloned())
}
/// Runs the main auto-brightness code.
/// This task monitors its running boolean and terminates if it goes false.
async fn get_current_brightness(backlight:
Arc<Mutex<dyn BacklightControl>>)
-> f32 {
let backlight = backlight.lock().await;
let fut = backlight.get_brightness();
match fut.await {
Ok(brightness) => brightness as f32,
Err(e) => {
if *GET_BRIGHTNESS_FAILED_FIRST.lock().await {
{
let lvl = ::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&584u32,
&::core::fmt::Arguments::new_v1(&["Failed to get backlight: ",
". assuming 1.0"],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl, "");
};
;
*GET_BRIGHTNESS_FAILED_FIRST.lock().await = false;
}
*LAST_SET_BRIGHTNESS.lock().await
}
}
}
async fn read_sensor_and_get_brightness(sensor:
Arc<Mutex<dyn SensorControl>>,
spline: &Spline<f32, f32>,
max_brightness: f64) -> f32 {
let lux =
{
let sensor = sensor.lock().await;
let fut = sensor.read();
let report =
fut.await.expect("Could not read from the sensor");
report.illuminance
};
brightness_curve_lux_to_nits(lux, spline).await /
max_brightness as f32
}
async fn brightness_curve_lux_to_nits(lux: u16, spline: &Spline<f32, f32>)
-> f32 {
let result = (*spline).clamped_sample(lux as f32);
match result { Some(nits) => { return nits; } None => return 1.0, }
}
/// Sets the brightness of the backlight to a specific value.
/// An abortable task is spawned to handle this as it can take a while to do.
async fn set_brightness(value: f32,
set_brightness_abort_handle:
Arc<Mutex<Option<AbortHandle>>>,
backlight: Arc<Mutex<dyn BacklightControl>>,
current_sender_channel:
Arc<Mutex<SenderChannel<f32>>>) {
let value = num_traits::clamp(value, 0.0, 1.0);
let current_value = get_current_brightness(backlight.clone()).await;
if (current_value - value).abs() >= BRIGHTNESS_STEP_SIZE {
let mut set_brightness_abort_handle =
set_brightness_abort_handle.lock().await;
if let Some(handle) = set_brightness_abort_handle.take() {
handle.abort();
}
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let backlight = backlight.clone();
let current_sender_channel = current_sender_channel.clone();
fasync::Task::spawn(Abortable::new(async move
{
set_brightness_impl(value,
backlight,
current_sender_channel).await;
},
abort_registration).unwrap_or_else(|_task_aborted|
())).detach();
*set_brightness_abort_handle = Some(abort_handle);
} else if (current_value - value).abs() > BRIGHTNESS_MINIMUM_CHANGE {
set_brightness_impl(value, backlight,
current_sender_channel).await;
}
}
async fn set_brightness_impl(value: f32,
backlight: Arc<Mutex<dyn BacklightControl>>,
current_sender_channel:
Arc<Mutex<SenderChannel<f32>>>) {
let current_value = get_current_brightness(backlight.clone()).await;
let mut backlight = backlight.lock().await;
let set_brightness =
|value|
{
backlight.set_brightness(value).unwrap_or_else(|e|
{
let lvl =
::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/control.rs".trim_start_matches("../"),
&662u32,
&::core::fmt::Arguments::new_v1(&["Failed to set backlight: "],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl,
"");
})
};
let current_sender_channel = current_sender_channel.clone();
set_brightness_slowly(current_value, value, set_brightness,
*BRIGHTNESS_CHANGE_DURATION.lock().await,
current_sender_channel).await;
}
/// Change the brightness of the screen slowly to `nits` nits. We don't want to change the screen
/// suddenly so we smooth the transition by doing it in a series of small steps.
/// The time per step can be changed if needed e.g. to fade up slowly and down quickly.
/// When testing we set time_per_step to zero.
async fn set_brightness_slowly(current_value: f32, to_value: f32,
mut set_brightness: impl FnMut(f64),
duration: Duration,
current_sender_channel:
Arc<Mutex<SenderChannel<f32>>>) {
let mut current_value = current_value;
let to_value = num_traits::clamp(to_value, 0.0, 1.0);
if !(to_value <= 1.0) {
::core::panicking::panic("assertion failed: to_value <= 1.0")
};
if !(current_value <= 1.0) {
::core::panicking::panic("assertion failed: current_value <= 1.0")
};
let current_sender_channel = current_sender_channel.clone();
let difference = to_value - current_value;
let steps = (difference.abs() / BRIGHTNESS_STEP_SIZE) as u16;
if steps > 0 {
let time_per_step =
cmp::min(duration / steps,
MAX_BRIGHTNESS_STEP_TIME_MS.millis());
let step_size = difference / steps as f32;
for _i in 0..steps {
let current_sender_channel = current_sender_channel.clone();
current_value = current_value + step_size;
set_brightness(current_value as f64);
current_sender_channel.lock().await.send_value(current_value);
if time_per_step.into_millis() > 0 {
fuchsia_async::Timer::new(time_per_step.after_now()).await;
}
}
}
set_brightness(to_value as f64);
current_sender_channel.lock().await.send_value(current_value);
*LAST_SET_BRIGHTNESS.lock().await = to_value;
}
}
mod sender_channel {
use futures::channel::mpsc::UnboundedSender;
use parking_lot::RwLock;
use std::sync::Arc;
/// Class for storing a list of senders and certain operations on them.
/// add_sender_channel adds a sender to the list.
/// send_value sends the new_value to the receivers.
/// If there is a new channel, the sender will be added to the list in the class.
/// Whenever value is changed, every sender in the list should send the new value to the sender.
/// If the channel is closed, remove corresponding sender from the list.
pub struct SenderChannel<T> {
pub sender_channel_vec: Arc<RwLock<Vec<UnboundedSender<T>>>>,
}
impl <T> SenderChannel<T> where T: Copy {
pub fn new() -> SenderChannel<T> {
SenderChannel{sender_channel_vec:
Arc::new(RwLock::new(Vec::new())),}
}
pub async fn add_sender_channel(&mut self,
sender: UnboundedSender<T>) {
self.sender_channel_vec.write().push(sender);
}
pub fn send_value(&mut self, new_value: T) {
let mut sender_channel_vec = self.sender_channel_vec.write();
sender_channel_vec.retain(|sender|
{
let sender_success =
sender.unbounded_send(new_value);
match sender_success {
Ok(_v) => true,
Err(_e) => false,
}
})
}
}
}
mod sensor {
use std::path::Path;
use std::{fs, io};
use anyhow::{format_err, Context as _, Error};
use async_trait::async_trait;
use byteorder::{ByteOrder, LittleEndian};
use fidl_fuchsia_hardware_input::{DeviceMarker as SensorMarker,
DeviceProxy as SensorProxy, ReportType};
use fuchsia_syslog::fx_log_info;
/// Unique signature for the light sensor
const HID_SENSOR_DESCRIPTOR: [u8; 4] = [5, 32, 9, 65];
pub struct AmbientLightInputRpt {
pub rpt_id: u8,
pub state: u8,
pub event: u8,
pub illuminance: u16,
pub red: u16,
pub green: u16,
pub blue: u16,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for AmbientLightInputRpt {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
AmbientLightInputRpt {
rpt_id: ref __self_0_0,
state: ref __self_0_1,
event: ref __self_0_2,
illuminance: ref __self_0_3,
red: ref __self_0_4,
green: ref __self_0_5,
blue: ref __self_0_6 } => {
let debug_trait_builder =
&mut ::core::fmt::Formatter::debug_struct(f,
"AmbientLightInputRpt");
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"rpt_id",
&&(*__self_0_0));
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"state",
&&(*__self_0_1));
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"event",
&&(*__self_0_2));
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"illuminance",
&&(*__self_0_3));
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"red",
&&(*__self_0_4));
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"green",
&&(*__self_0_5));
let _ =
::core::fmt::DebugStruct::field(debug_trait_builder,
"blue",
&&(*__self_0_6));
::core::fmt::DebugStruct::finish(debug_trait_builder)
}
}
}
}
/// Opens the sensor's device file.
/// Tries all the input devices until the one with the correct signature is found.
async fn open_sensor() -> Result<SensorProxy, Error> {
let input_devices_directory = "/dev/class/input";
let path = Path::new(input_devices_directory);
let entries = fs::read_dir(path)?;
for entry in entries {
let entry = entry?;
let device =
open_input_device(entry.path().to_str().expect("Bad path"))?;
if let Ok(device_descriptor) = device.get_report_desc().await {
if device_descriptor.len() < 4 {
return Err(::anyhow::private::new_adhoc("Short HID header"));
}
let device_header = &device_descriptor[0..4];
if device_header == HID_SENSOR_DESCRIPTOR {
return Ok(device);
}
}
}
Err(io::Error::new(io::ErrorKind::NotFound, "no sensor found").into())
}
/// Reads the sensor's HID record and decodes it.
async fn read_sensor(sensor: &SensorProxy)
-> Result<AmbientLightInputRpt, Error> {
let report = sensor.get_report(ReportType::Input, 1).await?;
let report = report.1;
if report.len() < 11 {
return Err(::anyhow::private::new_adhoc("Sensor HID report too short"));
}
Ok(AmbientLightInputRpt{rpt_id: report[0],
state: report[1],
event: report[2],
illuminance:
LittleEndian::read_u16(&report[3..5]),
red: LittleEndian::read_u16(&report[5..7]),
blue: LittleEndian::read_u16(&report[7..9]),
green:
LittleEndian::read_u16(&report[9..11]),})
}
/// TODO(lingxueluo) Default and temporary report when sensor is not valid(fxbug.dev/42782).
fn default_report() -> Result<AmbientLightInputRpt, Error> {
Ok(AmbientLightInputRpt{rpt_id: 0,
state: 0,
event: 0,
illuminance: 200,
red: 200,
green: 200,
blue: 200,})
}
fn open_input_device(path: &str) -> Result<SensorProxy, Error> {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Opening sensor at "],
&match (&path,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Debug::fmt)],
}),
lvl, "");
};
;
let (proxy, server) =
fidl::endpoints::create_proxy::<SensorMarker>().context("Failed to create sensor proxy")?;
fdio::service_connect(path,
server.into_channel()).context("Failed to connect built-in service")?;
Ok(proxy)
}
pub struct Sensor {
proxy: Option<SensorProxy>,
}
impl Sensor {
pub async fn new() -> Sensor {
let proxy = open_sensor().await;
match proxy {
Ok(proxy) => return Sensor{proxy: Some(proxy),},
Err(_e) => {
{
::std::io::_print(::core::fmt::Arguments::new_v1(&["No valid sensor found.\n"],
&match ()
{
()
=>
[],
}));
};
return Sensor{proxy: None,};
}
}
}
async fn read(&self) -> Result<AmbientLightInputRpt, Error> {
if self.proxy.is_none() {
default_report()
} else { read_sensor(self.proxy.as_ref().unwrap()).await }
}
}
pub trait SensorControl: Send {
#[must_use]
fn read<'life0, 'async_trait>(&'life0 self)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
Result<AmbientLightInputRpt,
Error>> +
::core::marker::Send + 'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait;
}
impl SensorControl for Sensor {
fn read<'life0, 'async_trait>(&'life0 self)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
Result<AmbientLightInputRpt,
Error>> +
::core::marker::Send + 'async_trait>> where
'life0: 'async_trait, Self: 'async_trait {
#[allow(unused_parens, clippy :: missing_docs_in_private_items,
clippy :: needless_lifetimes, clippy :: ptr_arg, clippy ::
trivially_copy_pass_by_ref, clippy ::
type_repetition_in_bounds, clippy ::
used_underscore_binding,)]
async fn __read(_self: &Sensor)
-> Result<AmbientLightInputRpt, Error> {
_self.read().await
}
Box::pin(__read::<>(self))
}
}
}
const ADJUSTMENT_DELTA: f32 = 0.1;
async fn run_brightness_server(mut stream: ControlRequestStream,
control: Arc<Mutex<dyn ControlTrait>>)
-> Result<(), Error> {
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["New brightness server"],
&match ()
{
() =>
[],
}), lvl,
"");
};
;
let (initial_current, initial_auto) =
get_initial_value(control.clone()).await?;
let watch_auto_handler:
Arc<Mutex<WatchHandler<bool, WatcherAutoResponder>>> =
Arc::new(Mutex::new(WatchHandler::create(Some(initial_auto))));
let (auto_channel_sender, auto_channel_receiver) =
futures::channel::mpsc::unbounded::<bool>();
let watch_current_handler:
Arc<Mutex<WatchHandler<f32, WatcherCurrentResponder>>> =
Arc::new(Mutex::new(WatchHandler::create(Some(initial_current))));
let (current_channel_sender, current_channel_receiver) =
futures::channel::mpsc::unbounded::<f32>();
let watch_adjustment_handler:
Arc<Mutex<WatchHandler<f32, WatcherAdjustmentResponder>>> =
Arc::new(Mutex::new(WatchHandler::create_with_change_fn(Box::new(move
|old_data:
&f32,
new_data:
&f32|
{
(*new_data
-
*old_data).abs()
>=
ADJUSTMENT_DELTA
}),
Some(0.0))));
let (adjustment_channel_sender, adjustment_channel_receiver) =
futures::channel::mpsc::unbounded::<f32>();
let control_clone = control.clone();
{
let mut control = control_clone.lock().await;
control.add_current_sender_channel(current_channel_sender).await;
control.add_auto_sender_channel(auto_channel_sender).await;
control.add_adjustment_sender_channel(adjustment_channel_sender).await;
}
let listen_current_task_abort_handle =
start_listen_task(watch_current_handler.clone(),
Arc::new(Mutex::new(current_channel_receiver)));
let listen_auto_task_abort_handle =
start_listen_task(watch_auto_handler.clone(),
Arc::new(Mutex::new(auto_channel_receiver)));
let listen_adjustment_task_abort_handle =
start_listen_task(watch_adjustment_handler.clone(),
Arc::new(Mutex::new(adjustment_channel_receiver)));
while let Some(request) =
stream.try_next().await.context("error running brightness server")?
{
let mut control = control.lock().await;
control.handle_request(request, watch_current_handler.clone(),
watch_auto_handler.clone(),
watch_adjustment_handler.clone()).await;
}
listen_current_task_abort_handle.abort();
listen_auto_task_abort_handle.abort();
listen_adjustment_task_abort_handle.abort();
Ok(())
}
fn start_listen_task<T: std::marker::Send,
ST: std::marker::Send>(watch_handler:
Arc<Mutex<WatchHandler<T,
ST>>>,
receiver:
Arc<Mutex<UnboundedReceiver<T>>>)
-> AbortHandle where T: std::clone::Clone + 'static,
ST: watch_handler::Sender<T> + 'static {
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let receiver = receiver.clone();
fasync::Task::spawn(Abortable::new(async move
{
while let Some(value) =
receiver.lock().await.next().await
{
let mut handler_lock =
watch_handler.lock().await;
handler_lock.set_value(value);
}
},
abort_registration).unwrap_or_else(|_|
())).detach();
abort_handle
}
async fn get_initial_value(control: Arc<Mutex<dyn ControlTrait>>)
-> Result<(f32, bool), Error> {
let mut control = control.lock().await;
let (backlight, auto_brightness_on) =
control.get_backlight_and_auto_brightness_on();
let backlight = backlight.lock().await;
let initial_brightness =
backlight.get_brightness().await.unwrap_or_else(|e|
{
{
let lvl =
::fuchsia_syslog::levels::ERROR;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["[",
"(",
")] "],
&match (&"../../src/ui/bin/brightness_manager/src/main.rs".trim_start_matches("../"),
&130u32,
&::core::fmt::Arguments::new_v1(&["Didn\'t get the initial brightness in watch due to err ",
", assuming 1.0."],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt)],
}))
{
(arg0,
arg1,
arg2)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg1,
::core::fmt::Display::fmt),
::core::fmt::ArgumentV1::new(arg2,
::core::fmt::Display::fmt)],
}),
lvl,
"");
};
;
1.0
});
Ok((initial_brightness as f32, auto_brightness_on))
}
async fn run_brightness_service(fs:
ServiceFs<ServiceObjLocal<'static,
ControlRequestStream>>,
control: Arc<Mutex<dyn ControlTrait>>,
run_server:
impl Fn(ControlRequestStream,
Arc<Mutex<dyn ControlTrait>>)
->
Pin<Box<dyn Future<Output =
Result<(),
Error>>>>)
-> Result<(), Error> {
const MAX_CONCURRENT: usize = 10_000;
let fut =
fs.for_each_concurrent(MAX_CONCURRENT,
|stream|
{
let control = control.clone();
run_server(stream,
control).unwrap_or_else(|e|
{
let lvl =
::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&[""],
&match (&e,)
{
(arg0,)
=>
[::core::fmt::ArgumentV1::new(arg0,
::core::fmt::Debug::fmt)],
}),
lvl,
"");
})
});
fut.await;
Ok(())
}
fn main() -> Result<(), Error> {
async fn func() -> Result<(), Error> {
{
fuchsia_syslog::init_with_tags(&["brightness"])?;
{
let lvl = ::fuchsia_syslog::levels::INFO;
::fuchsia_syslog::log_helper(::core::fmt::Arguments::new_v1(&["Started"],
&match ()
{
()
=>
[],
}),
lvl, "");
};
;
let mut fs = ServiceFs::new_local();
fs.dir("svc").add_fidl_service(|stream: ControlRequestStream|
stream);
fs.take_and_serve_directory_handle()?;
let backlight = Backlight::new().await?;
let backlight = Arc::new(Mutex::new(backlight));
let sensor = Sensor::new().await;
let sensor = Arc::new(Mutex::new(sensor));
let current_sender_channel: SenderChannel<f32> =
SenderChannel::new();
let current_sender_channel =
Arc::new(Mutex::new(current_sender_channel));
let auto_sender_channel: SenderChannel<bool> =
SenderChannel::new();
let auto_sender_channel =
Arc::new(Mutex::new(auto_sender_channel));
let adjustment_sender_channel: SenderChannel<f32> =
SenderChannel::new();
let adjustment_sender_channel =
Arc::new(Mutex::new(adjustment_sender_channel));
let control =
Control::new(sensor, backlight, current_sender_channel,
auto_sender_channel,
adjustment_sender_channel).await;
let control = Arc::new(Mutex::new(control));
let run_server:
fn(stream: ControlRequestStream,
control: Arc<Mutex<dyn ControlTrait>>)
-> Pin<Box<dyn Future<Output = Result<(), Error>>>> =
|stream, control|
Box::pin(run_brightness_server(stream, control));
run_brightness_service(fs, control, run_server).await?;
Ok(())
}
}
::fuchsia_async::Executor::new().expect("Failed to create executor").run_singlethreaded(func())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment