Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1d0a14b authored by Zhi Dou's avatar Zhi Dou
Browse files

aconfig: add exported mode in c/c++ codegen

This commit adds exported mode to c/c++ codegen.

When the codegen mode is exported
1. only flags with exported: true will be generated
2. the generated getter should be in a read_write format and with
   default value as false, regardless the original permission and state
   of the flag

This change moves process parsed_flags funciton into codegen crate. The
process function is used to process parsed_flags based on the codegen
mode.

The template has also modified to keep readability.

Bug: 316357680
Test: atest aconfig.test aconfig.test.cpp aconfig.test.cpp.test_mode

Change-Id: I511e05ab93b07a04236055d956d1926f4ed89f36
parent 4dc569ae
Loading
Loading
Loading
Loading
+113 −8
Original line number Diff line number Diff line
@@ -49,7 +49,9 @@ where
        has_fixed_read_only,
        readwrite,
        readwrite_count,
        for_test: codegen_mode == CodegenMode::Test,
        is_test_mode: codegen_mode == CodegenMode::Test,
        is_prod_mode: codegen_mode == CodegenMode::Production,
        is_exported_mode: codegen_mode == CodegenMode::Exported,
        class_elements,
    };

@@ -92,7 +94,9 @@ pub struct Context<'a> {
    pub has_fixed_read_only: bool,
    pub readwrite: bool,
    pub readwrite_count: i32,
    pub for_test: bool,
    pub is_test_mode: bool,
    pub is_prod_mode: bool,
    pub is_exported_mode: bool,
    pub class_elements: Vec<ClassElement>,
}

@@ -400,6 +404,48 @@ void com_android_aconfig_test_reset_flags();
#endif


"#;

    const EXPORTED_EXPORTED_HEADER_EXPECTED: &str = r#"
#pragma once

#ifdef __cplusplus

#include <memory>

namespace com::android::aconfig::test {

class flag_provider_interface {
public:
    virtual ~flag_provider_interface() = default;

    virtual bool disabled_rw_exported() = 0;

    virtual bool enabled_ro_exported() = 0;
};

extern std::unique_ptr<flag_provider_interface> provider_;

inline bool disabled_rw_exported() {
    return provider_->disabled_rw_exported();
}

inline bool enabled_ro_exported() {
    return provider_->enabled_ro_exported();
}

}

extern "C" {
#endif // __cplusplus

bool com_android_aconfig_test_disabled_rw_exported();

bool com_android_aconfig_test_enabled_ro_exported();

#ifdef __cplusplus
} // extern "C"
#endif
"#;

    const PROD_SOURCE_FILE_EXPECTED: &str = r#"
@@ -731,6 +777,55 @@ void com_android_aconfig_test_reset_flags() {
     com::android::aconfig::test::reset_flags();
}

"#;

    const EXPORTED_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test.h"
#include <server_configurable_flags/get_flags.h>
#include <vector>

namespace com::android::aconfig::test {

    class flag_provider : public flag_provider_interface {
        public:
            virtual bool disabled_rw_exported() override {
                if (cache_[0] == -1) {
                    cache_[0] = server_configurable_flags::GetServerConfigurableFlag(
                        "aconfig_flags.aconfig_test",
                        "com.android.aconfig.test.disabled_rw_exported",
                        "false") == "true";
                }
                return cache_[0];
            }

            virtual bool enabled_ro_exported() override {
                if (cache_[1] == -1) {
                    cache_[1] = server_configurable_flags::GetServerConfigurableFlag(
                        "aconfig_flags.aconfig_test",
                        "com.android.aconfig.test.enabled_ro_exported",
                        "false") == "true";
                }
                return cache_[1];
            }


    private:
        std::vector<int8_t> cache_ = std::vector<int8_t>(2, -1);
    };

    std::unique_ptr<flag_provider_interface> provider_ =
        std::make_unique<flag_provider>();
}

bool com_android_aconfig_test_disabled_rw_exported() {
    return com::android::aconfig::test::disabled_rw_exported();
}

bool com_android_aconfig_test_enabled_ro_exported() {
    return com::android::aconfig::test::enabled_ro_exported();
}


"#;

    const READ_ONLY_EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
@@ -854,11 +949,10 @@ bool com_android_aconfig_test_enabled_ro() {
        expected_header: &str,
        expected_src: &str,
    ) {
        let generated = generate_cpp_code(
            crate::test::TEST_PACKAGE,
            parsed_flags.parsed_flag.into_iter(),
            mode,
        )
        let modified_parsed_flags =
            crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode);
        let generated =
            generate_cpp_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode)
                .unwrap();
        let mut generated_files_map = HashMap::new();
        for file in generated {
@@ -911,6 +1005,17 @@ bool com_android_aconfig_test_enabled_ro() {
        );
    }

    #[test]
    fn test_generate_cpp_code_for_exported() {
        let parsed_flags = crate::test::parse_test_flags();
        test_generate_cpp_code(
            parsed_flags,
            CodegenMode::Exported,
            EXPORTED_EXPORTED_HEADER_EXPECTED,
            EXPORTED_SOURCE_FILE_EXPECTED,
        );
    }

    #[test]
    fn test_generate_cpp_code_for_read_only_prod() {
        let parsed_flags = crate::test::parse_read_only_test_flags();
+51 −3
Original line number Diff line number Diff line
@@ -207,12 +207,12 @@ pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Ve

pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
    let parsed_flags = input.try_parse_flags()?;
    let filtered_parsed_flags = filter_parsed_flags(parsed_flags, codegen_mode);
    let Some(package) = find_unique_package(&filtered_parsed_flags) else {
    let modified_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, codegen_mode);
    let Some(package) = find_unique_package(&modified_parsed_flags) else {
        bail!("no parsed flags, or the parsed flags use different packages");
    };
    let package = package.to_string();
    generate_cpp_code(&package, filtered_parsed_flags.into_iter(), codegen_mode)
    generate_cpp_code(&package, modified_parsed_flags.into_iter(), codegen_mode)
}

pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
@@ -335,6 +335,30 @@ fn filter_parsed_flags(
    }
}

pub fn modify_parsed_flags_based_on_mode(
    parsed_flags: ProtoParsedFlags,
    codegen_mode: CodegenMode,
) -> Vec<ProtoParsedFlag> {
    fn exported_mode_flag_modifier(mut parsed_flag: ProtoParsedFlag) -> ProtoParsedFlag {
        parsed_flag.set_state(ProtoFlagState::DISABLED);
        parsed_flag.set_permission(ProtoFlagPermission::READ_WRITE);
        parsed_flag.set_is_fixed_read_only(false);
        parsed_flag
    }

    match codegen_mode {
        CodegenMode::Exported => parsed_flags
            .parsed_flag
            .into_iter()
            .filter(|pf| pf.is_exported())
            .map(exported_mode_flag_modifier)
            .collect(),
        CodegenMode::Production | CodegenMode::Test => {
            parsed_flags.parsed_flag.into_iter().collect()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
@@ -624,4 +648,28 @@ mod tests {
        let reader = Box::new(cursor);
        Input { source: "test.data".to_string(), reader }
    }

    #[test]
    fn test_modify_parsed_flags_based_on_mode_prod() {
        let parsed_flags = crate::test::parse_test_flags();
        let p_parsed_flags =
            modify_parsed_flags_based_on_mode(parsed_flags.clone(), CodegenMode::Production);
        assert_eq!(parsed_flags.parsed_flag.len(), p_parsed_flags.len());
        for (i, item) in p_parsed_flags.iter().enumerate() {
            assert!(parsed_flags.parsed_flag[i].eq(item));
        }
    }

    #[test]
    fn test_modify_parsed_flags_based_on_mode_exported() {
        let parsed_flags = crate::test::parse_test_flags();
        let p_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, CodegenMode::Exported);
        assert_eq!(2, p_parsed_flags.len());
        for flag in p_parsed_flags.iter() {
            assert_eq!(ProtoFlagState::DISABLED, flag.state());
            assert_eq!(ProtoFlagPermission::READ_WRITE, flag.permission());
            assert!(!flag.is_fixed_read_only());
            assert!(flag.is_exported());
        }
    }
}
+14 −8
Original line number Diff line number Diff line
#pragma once

{{ if not for_test- }}
{{ if not is_test_mode- }}
{{ if has_fixed_read_only- }}
#ifndef {package_macro}
#define {package_macro}(FLAG) {package_macro}_##FLAG
@@ -29,12 +29,12 @@ public:
    {{ for item in class_elements}}
    virtual bool {item.flag_name}() = 0;

    {{ if for_test- }}
    {{ if is_test_mode }}
    virtual void {item.flag_name}(bool val) = 0;
    {{ -endif }}
    {{ -endfor }}

    {{ if for_test }}
    {{ if is_test_mode }}
    virtual void reset_flags() \{}
    {{ -endif }}
};
@@ -43,9 +43,10 @@ extern std::unique_ptr<flag_provider_interface> provider_;

{{ for item in class_elements}}
inline bool {item.flag_name}() \{
    {{ if for_test- }}
    {{ if is_test_mode }}
    return provider_->{item.flag_name}();
    {{ -else- }}
    {{ if is_prod_mode- }}
    {{ if item.readwrite- }}
    return provider_->{item.flag_name}();
    {{ -else- }}
@@ -55,17 +56,22 @@ inline bool {item.flag_name}() \{
    return {item.default_value};
    {{ -endif }}
    {{ -endif }}
    {{ -else- }}
    {{ if is_exported_mode- }}
    return provider_->{item.flag_name}();
    {{ -endif }}
    {{ -endif }}
    {{ -endif }}
}

{{ if for_test- }}
{{ if is_test_mode }}
inline void {item.flag_name}(bool val) \{
    provider_->{item.flag_name}(val);
}
{{ -endif }}
{{ -endfor }}

{{ if for_test- }}
{{ if is_test_mode }}
inline void reset_flags() \{
    return provider_->reset_flags();
}
@@ -79,12 +85,12 @@ extern "C" \{
{{ for item in class_elements }}
bool {header}_{item.flag_name}();

{{ if for_test- }}
{{ if is_test_mode }}
void set_{header}_{item.flag_name}(bool val);
{{ -endif }}
{{ -endfor }}

{{ if for_test- }}
{{ if is_test_mode }}
void {header}_reset_flags();
{{ -endif }}

+24 −7
Original line number Diff line number Diff line
@@ -2,9 +2,8 @@

{{ if readwrite- }}
#include <server_configurable_flags/get_flags.h>
{{ -endif }}

{{ if for_test- }}
{{ endif }}
{{ if is_test_mode }}
#include <unordered_map>
#include <string>
{{ -else- }}
@@ -15,7 +14,7 @@

namespace {cpp_namespace} \{

{{ if for_test- }}
{{ if is_test_mode }}
    class flag_provider : public flag_provider_interface \{
    private:
        std::unordered_map<std::string, bool> overrides_;
@@ -59,6 +58,7 @@ namespace {cpp_namespace} \{

        {{ for item in class_elements }}
        virtual bool {item.flag_name}() override \{
            {{ if is_prod_mode- }}
            {{ if item.readwrite- }}
            if (cache_[{item.readwrite_idx}] == -1) \{
                cache_[{item.readwrite_idx}] = server_configurable_flags::GetServerConfigurableFlag(
@@ -74,6 +74,17 @@ namespace {cpp_namespace} \{
            return {item.default_value};
            {{ -endif }}
            {{ -endif }}
            {{ -else- }}
            {{ if is_exported_mode-}}
            if (cache_[{item.readwrite_idx}] == -1) \{
                cache_[{item.readwrite_idx}] = server_configurable_flags::GetServerConfigurableFlag(
                    "aconfig_flags.{item.device_config_namespace}",
                    "{item.device_config_flag}",
                    "false") == "true";
            }
            return cache_[{item.readwrite_idx}];
            {{ -endif }}
            {{ -endif }}
        }
        {{ endfor }}
    {{ if readwrite- }}
@@ -91,9 +102,10 @@ std::unique_ptr<flag_provider_interface> provider_ =

{{ for item in class_elements }}
bool {header}_{item.flag_name}() \{
    {{ if for_test- }}
    {{ if is_test_mode }}
    return {cpp_namespace}::{item.flag_name}();
    {{ -else- }}
    {{ if is_prod_mode- }}
    {{ if item.readwrite- }}
    return {cpp_namespace}::{item.flag_name}();
    {{ -else- }}
@@ -103,17 +115,22 @@ bool {header}_{item.flag_name}() \{
    return {item.default_value};
    {{ -endif }}
    {{ -endif }}
    {{ -else- }}
    {{ if is_exported_mode- }}
    return {cpp_namespace}::{item.flag_name}();
    {{ -endif }}
    {{ -endif }}
    {{ -endif }}
}

{{ if for_test- }}
{{ if is_test_mode }}
void set_{header}_{item.flag_name}(bool val) \{
    {cpp_namespace}::{item.flag_name}(val);
}
{{ -endif }}
{{ endfor-}}

{{ if for_test }}
{{ if is_test_mode }}
void {header}_reset_flags() \{
     {cpp_namespace}::reset_flags();
}