# Android Audio Flagging Guide

This directory contains the aconfig flag definitions and the associated build files for Android
Audio features.

## Build Configuration

### Namespaces

There are several global namespaces involved with flagging which must be maintained:
 - **Mendel project**: `media_audio`. Associated with mdb group and used by gantry.
All aconfig flags in this namespace should be defined in this directory, and all flags defined in
this directory should belong to this namespace.
 - **Blueprint namespaces**: the name field of any module is unique over a particular build
namespace (for platform development purposes there is one).
 - **Aconfig package**: All flags generated by aconfig are converted by Halyard into Mendel flags
of the form {PACKAGE}{FLAG}, where both fields are stripped of spaces, underscores and dashes. This
combo **must** be globally unique (across Android).
 - **Generated code**: Both java and cpp aconfig library rules generate code which pollutes the
namespace of the backend. This means that if two aconfig java libraries exist which consume **any**
`aconfig_declarations` with packages which intersect, these libraries are incompatible to be linked
together (and equivalent in cc). If the library is included in the framework, it is on the
bootclasspath, so no other library for that package can exist. Additionally, the cpp backend
generates header files with the same name as the unqualified name of the package which means
include path conflicts are possible.


### Naming convention

Given above, follow the following naming convention (given a `{PACKAGE}`).

Generally, `aconfig_declarations` and `{backend}_aconfig_library` should be 1-1, except in cases
where different package configurations are needed with pre-processing with different classpaths.
This is because multiple libraries with the same aconfig package cannot compile together.

```
aconfig_declarations {
    name: "{PACKAGE}-aconfig",
    package: "{PACKAGE}",
    srcs: ["{PACKAGE}.aconfig"]
}

{backend}_aconfig_library {
    name: "{PACKAGE}-aconfig-{backend}",
    aconfig_declarations: "{PACKAGE}-aconfig",
    defaults: ["audio-aconfig-{backend}-defaults"],
}

```
If the flags are required as part of the framework, the java backend is ingested into the framework
via srcjar for cyclic dependency/simplicity reasons. Add the following

```
    ":{PACKAGE}-aconfig-java{.generated_srcjars}"
```

as a source in `audio-framework-aconfig`. This target is included in the file-list which compiles
the framework. If a lib is included in this list, it is unecessary to add it in any other blueprint
file for platform code (for non-host). For tests, the library should be **statically** linked
(which shadows the bootclasspath), to get around @hide restrictions (this approach may change).


### Visibility

Visibility should be controlled (private) so that flag cleanup remains maintainable by the team.
This constraints the locations where extant flags need to be chased for removal.


### Packaging preference
As a rule, prefer the most constrained package appropriate for a particular flag. This limits viral
dependencies on a flag library which restricts where/how testing can occur. It also speeds up
incremental rebuilds. Packages which end up in the framework should be avoided as much as possible,
since they require rebuilding the framework, pollute the bootclasspath, and require special build
handling to operate (srcjar generation, jarjar to access in CTS).

Utilize "java-like" package naming for all packages, to ensure packages are globally unique, and
to avoid class conflicts if these flags are later included in java code.

## Workflow

### Usage Style
In general, prefer flags at the integration level, rather than at the implementation level.
This allows flags to be queried in as few locations as possible such as by (parametrizing functions,
classes, types, etc.) It also allows callers to make different decisions on when behavior can/should
be changed (e.g. different flags could be used for different libraries).  This follows dependency
injection principles and ensures that global state has a smaller blast radius, and also makes it
easier to test code by relying less on infrastructure. The more places a flag is queried, the more
its implementation should be deferred upwards, either by the injection interfaces, or by explicit
parametrization.

### Flag scope
In general, flags should be scoped as precisely as possible while retaining orthogonality. If
flags are too specific (multiple flags interact together to encompass a single change), then
reasoning about independently switching flags becomes difficult. Other than all-on and all-of
configurations, there is limited soak for flag combinations, so it is critical that flags
interact with each other minimally (although emergent properties are inevitable).
However, if flags are too general, graduating/reverting flags can carry too much behavior change,
the build graph degenerates, and 

### Instant Staging
In general, it is recommended that the moment a flag is added to the tree, it should be moved to
staging on gantry. There is no benefit to adding a flag but not moving into staging.
This allows:
1. Verification by treehugger in both pre/post-submit
1. Automatic configuration for feature development for local engineering workflows
1. Integration with other engineering features in development


### FlaggedApi
FlaggedApi operates differently than other types of flags since these flags only graduate at the
next API bump. These flags also must be exposed through the framework. FlaggedApis should only
operate over the same set of flags as an implementation if the implementation is entirely related
to the feature. Given the constraints on the flag lifetime, it is preferable to use a "regular"
flag for implementation, which can integrate/soak/ship/clean-up faster.

Additionally, unlike "regular" flags, @FlaggedApis are not effectively soaked, so like non-trunk
API development, they are heavily reliant on CTS to integrate.

On non-next configs, @FlaggedApi has no runtime control, but it is undefined for callers to
call a FlaggedApi without querying the status of the flag. The build itself is not changed on
staging. Anything which builds against the platform can see all @FlaggedApis.

Methods annotated FlaggedApis are changed for release finalization -- if an API is not in next,
it is stripped from the Sdk (and left @hide). If an API graduated to next, it is included fully
included in the Sdk, and the @FlaggedApi annotation is stripped.


### TestApis
TestApis do not require flagging, unless they are API additions associated with new features.
For testing existing features, we have full control over the set of callers.

### Api Changes
There is partial (work ongoing) support for modifying API surfaces. 
 - SystemApi -> public is supported
 - UAU -> SystemApi is supported, but the @UAU must remain until the flag is in next
Other modifications involving moving between surfaces, or annotation changes may not be supported:
check the [FAQ](https://g3doc.corp.google.com/company/teams/android-api-council/guidelines/faq.md?cl=head#i-cannot-use-flaggedapi-with-data-classes-generated-by-codegen)
for the up to date list of support.
