Declare an aconfig flag

You can use aconfig flags in Java, C, C++, and Rust code. The AOSP build system launches a tool called aconfig used to generate a language-specific library of methods you can use to access the value of each flag. Before you can generate the library, you must declare flags and add them to the build.

Declare an aconfig flag for Java

To declare an aconfig flag for Java:

  1. In a directory where the new code exists, create a file with the extension .aconfig, for example, my_new_aconfig_flag_declarations.aconfig. An aconfig file is a text proto file that follows a standard schema.

  2. Add a flag declaration similar to the following:

    package: "com.example.android.aconfig.demo.flags"
    container: "system"
    
    flag {
        name: "my_new_flag"
        namespace: "aconfig_demo_namespace"
        description: "This flag controls untested code"
        bug: "<none>"
    }
    

    Where:

    • package, when combined with the flag name, provides a unique key. In Java, setting package to foo.bar results in an autogenerated class named foo.bar.Flags. In C++, flag accessor methods would be named foo::bar::"flagname". Flags in the same declaration file belong to the same package, but multiple declaration files can contribute flags to the same package.
    • container defines a collection of code that is built and shipped together as a binary. Valid containers are system, vendor, system_ext, product, name.of.apex, and name.of.apk.

    • name contains the name of the flag containing only lowercase letters, underscores, and numbers.

    • namespace contains the namespace for contributions. You must work with the assigned Google reviewer to determine your namespace. If you're using feature launch flags to maintain stability of your own AOSP mirror, you can use namespace however you like.

    • description contains a brief description of the feature or change that is flagged.

    • bug is the bug number associated with the new code contribution. You must work with the assigned Google reviewer to determine your bug. If you're using feature launch flags to maintain stability of your own AOSP mirror, you can use your bug tracking number or use <none>.

  3. Save the file and exit the editor.

Set up the build

After you have declared your flag, set up the build so that it can generate the library code used to access the flag's value.

  1. In your Android.bp build file, add an aconfig_declarations section similar to the following:

    aconfig_declarations {
      name: "aconfig_demo_flags",
      package: "com.example.android.aconfig.demo.flags",
      srcs: [
        "my_new_aconfig_flag_declarations.aconfig"
      ],
    }
    

    Where:

    • name contains the name of the declaration containing only lowercase letters, underscores, and numbers.
    • package contains the same package name used in the declaration.
    • srcs contains the name of the .aconfig file where the flag is declared.
  2. Save the file and exit the editor.

Declare an aconfig flag for C and C++

To declare an aconfig flag for C and C++:

  1. In a directory where the new code exists, create a file with the extension .aconfig, for example, my_new_aconfig_flag_declarations.aconfig. An aconfig file is a text proto file that follows a standard schema.

  2. Add a flag declaration similar to the following:

    package: "com.example.android.aconfig.demo.flags"
    container: "system"
    
    flag {
        name: "my_new_flag"
        namespace: "aconfig_demo_namespace"
        description: "This flag controls untested code"
        bug: "<none>"
    }
    

    Where:

    • package, when combined with the flag name, provides a unique key. In Java, setting package to foo.bar results in an autogenerated class named foo.bar.Flags. In C++, flag accessor methods would be named foo::bar::"flagname". Flags in the same declaration file belong to the same package, but multiple declaration files can contribute flags to the same package.
    • container defines a collection of code that is built and shipped together as a binary. Valid containers are system, vendor, system_ext, product, name.of.apex, and name.of.apk.

    • name contains the name of the flag containing only lowercase letters, underscores, and numbers.

    • namespace contains the namespace for contributions. You must work with the assigned Google reviewer to determine your namespace. If you're using feature launch flags to maintain stability of your own AOSP mirror, you can use namespace however you like.

    • description contains a brief description of the feature or change that is flagged.

    • bug is the bug number associated with the new code contribution. You must work with the assigned Google reviewer to determine your bug. If you're using feature launch flags to maintain stability of your own AOSP mirror, you can use your bug tracking number or use <none>.

  3. Save the file and exit the editor.

Set up the build

After you have declared your flag, set up the build so that it can generate the library code used to access the flag's value.

  1. In your Android.bp build file, add a aconfig_declarations section similar to the following:

    aconfig_declarations {
      name: "aconfig_demo_flags",
      package: "com.example.android.aconfig.demo.flags",
      srcs: [
        "my_new_aconfig_flag_declarations.aconfig"
      ],
    }
    

    Where:

    • name contains the name of the declaration containing only lowercase letters, underscores, and numbers.
    • package contains the same package name used in the declaration.
    • srcs contains the name of the aconfig file where the flag is declared.
  2. In the same file, create a cc_aconfig_library target similar to the following:

    cc_aconfig_library {
        name: "aconfig_demo_flags_c_lib",
        aconfig_declarations: "aconfig_demo_flags",
    }
    

    Where:

    • name contains the name of the library containing only lowercase letters, underscores, and numbers.
    • aconfig_declarations contains the same name used in the declaration.

    The cc_aconfig_library build target invokes C or C++ Codegen, which creates a library with the generated code at build time.

    The CC aconfig library is similar to a CC library target, but has options like vendor_available, product_available, host_supported, and vndk. If the build target depending on this cc_aconfig_library requires certain type of variants, you might also need to add the corresponding setting in the CC aconfig library target. For example, if the parent build target has vendor_available set to true, you might also want to set vendor_available to true in this cc_aconfig_library target.

    After adding this build target, your code can access this library. You can include this library using static_lib or shared_lib syntax. Note if you want to add this library as a static_lib, add a shared_lib dependency on server_configurable_flags. Step 3 shows how to include the code generated flag library into libexample_cpp_lib.

  3. Create a target that uses the aconfig flags, such as the following example cc_library:

    cc_library {
        name: "libexample_cpp_lib",
        srcs: ["src/example_cpp_lib.cc"],
        double_loadable: true,
        cflags: [
            "-Wall",
            "-Werror",
            "-Wno-unused-function",
            "-Wno-unused-parameter",
        ],
        header_libs: [
            "jni_headers",
        ],
        shared_libs: [
            "server_configurable_flags",
        ],
        static_libs: [
            "aconfig_demo_flags_c_lib",
        ],
        export_include_dirs: ["src/include"],
    }
    

    Where:

    • shared_libs includes extra dependencies required for aconfig flags.
    • static_libs is the name of library that is created by the build per the cc_aconfig_library name field in step 2. By creating a cc_library entry with the static library name, you can now use the aconfig flags in your code.

Declare an aconfig flag for Rust

To declare an aconfig flag for Rust:

  1. In a directory where the new code exists, create a file with the extension .aconfig, for example, my_new_aconfig_flag_declarations.aconfig. An aconfig file is a text proto file that follows a standard schema.

  2. Add a flag declaration similar to the following:

    package: "com.example.android.aconfig.demo.flags"
    container: "system"
    
    flag {
        name: "my_new_flag"
        namespace: "aconfig_demo_namespace"
        description: "This flag controls untested code"
        bug: "<none>"
    }
    

    Where:

    • package, when combined with the flag name, provides a unique key. In Java, setting package to foo.bar results in an autogenerated class named foo.bar.Flags. In C++, flag accessor methods would be named foo::bar::"flagname". Flags in the same declaration file belong to the same package, but multiple declaration files can contribute flags to the same package.
    • container defines a collection of code that is built and shipped together as a binary. Valid containers are system, vendor, system_ext, product, name.of.apex, and name.of.apk.

    • name contains the name of the flag containing only lowercase letters, underscores, and numbers.

    • namespace contains the namespace for contributions. You must work with the assigned Google reviewer to determine your namespace. If you're using feature launch flags to maintain stability of your own AOSP mirror, you can use namespace however you like.

    • description contains a brief description of the feature or change that is flagged.

    • bug is the bug number associated with the new code contribution. You must work with the assigned Google reviewer to determine your bug. If you're using feature launch flags to maintain stability of your own AOSP mirror, you can use your bug tracking number or use <none>.

  3. Save the file and exit the editor.

Set up the build

After you have declared your flag, set up the build so that it can generate the library code used to access the flag's value.

  1. In your Android.bp build file, add a aconfig_declarations section similar to the following:

    aconfig_declarations {
      name: "aconfig_demo_flags",
      package: "com.example.android.aconfig.demo.flags",
      srcs: [
        "my_new_aconfig_flag_declarations.aconfig"
      ],
    }
    

    Where:

    • name contains the name of the declaration containing only lowercase letters, underscores, and numbers.
    • package contains the same package name used in the declaration.
    • srcs contains the name of the aconfig file where the flag is declared.
  2. Create a rust_aconfig_library target similar to the next example. This target invokes Rust Codegen and creates a Rust library with the generated code during build time.

    rust_aconfig_library {
      name: "libaconfig_demo_flags_rust",
      crate_name: "aconfig_demo_flags_rust",
      aconfig_declarations: "aconfig_demo_flags",
    }
    

    Where:

    • name contains the name of the declaration containing only lowercase letters, underscores, and numbers.
    • crate_name contains the same package name used in the declaration.
    • aconfig_declarations contains the same name used in the declaration.

    With this change, your code can depend on this Rust library.

  3. In the same file, create a rust_library entry similar to the following:

    rust_library {
      name: "libexample_lib",
      rustlibs: [
          "libaconfig_demo_flags_rust",
      ]
    }
    

    This sample allows your source code build targets libexample_demo_flags_rust to include the code generated flag library.

  4. Save the file and exit the editor.