blob: e548cdf8d365394d2bcc69db571b7e2ee4110439 [file] [log] [blame]
// Copyright 2024, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This module defines system properties used for mmd.
//!
//! System properties "mmd.<flag_name>" are defined per OEM.
//!
//! Server configrations "persist.device_config.mmd_native.<flag_name>" overrides the corresponding
//! system properties for in-field experiment on a small population.
use std::str::FromStr;
use std::time::Duration;
use flags_rust::GetServerConfigurableFlag;
use log::error;
use rustutils::system_properties;
const SERVER_CONFIG_NAMESPACE: &str = "mmd_native";
fn generate_property_name(flag_name: &str) -> String {
format!("mmd.{flag_name}")
}
/// bool system properties for mmd.
///
/// clippy::enum_variant_names is allowed because we may add more properties.
#[allow(clippy::enum_variant_names)]
pub enum BoolProp {
ZramEnabled,
ZramWritebackEnabled,
ZramWritebackHugeIdleEnabled,
ZramWritebackIdleEnabled,
ZramWritebackHugeEnabled,
ZramRecompressionEnabled,
ZramRecompressionHugeIdleEnabled,
ZramRecompressionIdleEnabled,
ZramRecompressionHugeEnabled,
}
impl BoolProp {
fn flag_name(&self) -> &'static str {
match self {
Self::ZramEnabled => "zram.enabled",
Self::ZramWritebackEnabled => "zram.writeback.enabled",
Self::ZramWritebackHugeIdleEnabled => "zram.writeback.huge_idle.enabled",
Self::ZramWritebackIdleEnabled => "zram.writeback.idle.enabled",
Self::ZramWritebackHugeEnabled => "zram.writeback.huge.enabled",
Self::ZramRecompressionEnabled => "zram.recompression.enabled",
Self::ZramRecompressionHugeIdleEnabled => "zram.recompression.huge_idle.enabled",
Self::ZramRecompressionIdleEnabled => "zram.recompression.idle.enabled",
Self::ZramRecompressionHugeEnabled => "zram.recompression.huge.enabled",
}
}
pub fn get(&self, default: bool) -> bool {
if let Some(v) = read(self.flag_name()) {
v
} else {
default
}
}
}
/// u64 system properties for mmd.
///
/// clippy::enum_variant_names is allowed because we may add more properties.
#[allow(clippy::enum_variant_names)]
pub enum U64Prop {
ZramWritebackMinBytes,
ZramWritebackMaxBytes,
ZramWritebackMaxBytesPerDay,
ZramWritebackMinFreeSpacePercentage,
ZramRecompressionThresholdMib,
}
impl U64Prop {
fn flag_name(&self) -> &'static str {
match self {
Self::ZramWritebackMinBytes => "zram.writeback.min_bytes",
Self::ZramWritebackMaxBytes => "zram.writeback.max_bytes",
Self::ZramWritebackMaxBytesPerDay => "zram.writeback.max_bytes_per_day",
Self::ZramWritebackMinFreeSpacePercentage => "zram.writeback.min_free_space_pct",
Self::ZramRecompressionThresholdMib => "zram.recompression.threshold_mib",
}
}
pub fn get(&self, default: u64) -> u64 {
if let Some(v) = read(self.flag_name()) {
v
} else {
default
}
}
}
/// Duration system properties for mmd in seconds.
///
/// clippy::enum_variant_names is allowed because we may add more properties.
#[allow(clippy::enum_variant_names)]
pub enum SecondsProp {
ZramWritebackBackoff,
ZramWritebackMinIdle,
ZramWritebackMaxIdle,
ZramRecompressionBackoff,
ZramRecompressionMinIdle,
ZramRecompressionMaxIdle,
}
impl SecondsProp {
fn flag_name(&self) -> &'static str {
match self {
Self::ZramWritebackBackoff => "zram.writeback.backoff_seconds",
Self::ZramWritebackMinIdle => "zram.writeback.min_idle_seconds",
Self::ZramWritebackMaxIdle => "zram.writeback.max_idle_seconds",
Self::ZramRecompressionBackoff => "zram.recompression.backoff_seconds",
Self::ZramRecompressionMinIdle => "zram.recompression.min_idle_seconds",
Self::ZramRecompressionMaxIdle => "zram.recompression.max_idle_seconds",
}
}
pub fn get(&self, default: Duration) -> Duration {
if let Some(v) = read::<u64>(self.flag_name()) {
Duration::from_secs(v)
} else {
default
}
}
}
/// String system properties for mmd.
///
/// clippy::enum_variant_names is allowed because we may add more properties.
#[allow(clippy::enum_variant_names)]
pub enum StringProp {
ZramSize,
ZramCompAlgorithm,
}
impl StringProp {
fn flag_name(&self) -> &'static str {
match self {
Self::ZramSize => "zram.size",
Self::ZramCompAlgorithm => "zram.comp_algorithm",
}
}
pub fn get(&self, default: &str) -> String {
read(self.flag_name()).unwrap_or_else(|| default.to_string())
}
}
fn read<T: FromStr>(flag_name: &str) -> Option<T> {
let value = GetServerConfigurableFlag(SERVER_CONFIG_NAMESPACE, flag_name, "");
if !value.is_empty() {
if let Ok(v) = value.parse() {
return Some(v);
}
error!("failed to parse server config flag: {flag_name}={value}");
}
// fallback if server flag is not set or broken.
let property_name = generate_property_name(flag_name);
match system_properties::read(&property_name) {
Ok(Some(v)) => {
if let Ok(v) = v.parse() {
return Some(v);
} else {
error!("failed to parse system property: {property_name}={v}");
}
}
Ok(None) => {}
Err(e) => {
error!("failed to read system property: {property_name} {e:?}");
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bool_prop_from_default() {
// We can't test system properties directly. Just a unit test for
// default value.
assert!(BoolProp::ZramWritebackEnabled.get(true));
assert!(!BoolProp::ZramWritebackEnabled.get(false));
}
#[test]
fn u64_prop_from_default() {
// We can't test system properties directly. Just a unit test for
// default value.
assert_eq!(U64Prop::ZramWritebackMinBytes.get(12345), 12345);
}
#[test]
fn seconds_prop_from_default() {
// We can't test system properties directly. Just a unit test for
// default value.
assert_eq!(
SecondsProp::ZramWritebackBackoff.get(Duration::from_secs(12345)),
Duration::from_secs(12345)
);
}
}