blob: 98add321b0f2a488ad02fd5f5b68c2470b550984 [file] [log] [blame]
package {package_name};
{{ -if not is_test_mode }}
{{ -if allow_instrumentation }}
{{ if not library_exported- }}{#- only new storage for prod mode #}
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
{{ -if runtime_lookup_required }}
import android.aconfig.storage.StorageInternalReader;
{{ -endif }}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
private static volatile boolean isCached = false;
{{ for flag in flag_elements }}
{{ -if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
{{ -endif }}
{{ -endfor }}
private void init() \{
try \{
StorageInternalReader reader = new StorageInternalReader("{container}", "{package_name}");
{{ for namespace_with_flags in namespace_flags }}
{{ -for flag in namespace_with_flags.flags }}
{{ if flag.is_read_write }}
{flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
{{ endif }}
{{ -endfor }}
{{ -endfor }}
} catch (Exception e) \{
// pass
} catch (NoClassDefFoundError e) \{
// for mainline module running on older devices.
// This should be replaces to version check, after the version bump.
}
isCached = true;
}
{{ -endif }}{#- end of runtime_lookup_required #}
{{ -for flag in flag_elements }}
@Override
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean {flag.method_name}() \{
{{ -if flag.is_read_write }}
if (!isCached) \{
init();
}
return {flag.method_name};
{{ -else }}
return {flag.default_value};
{{ -endif }}
}
{{ endfor }}
}
{{ -else- }}{#- device config for exproted mode #}
import android.os.Binder;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -for namespace_with_flags in namespace_flags }}
private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
{{ -endfor- }}
{{ for flag in flag_elements }}
{{ -if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
{{ -endif }}
{{ -endfor }}
{{ for namespace_with_flags in namespace_flags }}
private void load_overrides_{namespace_with_flags.namespace}() \{
final long ident = Binder.clearCallingIdentity();
try \{
Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
{{ -for flag in namespace_with_flags.flags }}
{{ -if flag.is_read_write }}
{flag.method_name} =
properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
{{ -endif }}
{{ -endfor }}
} catch (NullPointerException e) \{
throw new RuntimeException(
"Cannot read value from namespace {namespace_with_flags.namespace} "
+ "from DeviceConfig. It could be that the code using flag "
+ "executed before SettingsProvider initialization. Please use "
+ "fixed read-only flag by adding is_fixed_read_only: true in "
+ "flag declaration.",
e
);
} catch (SecurityException e) \{
// for isolated process case, skip loading flag value from the storage, use the default
} finally \{
Binder.restoreCallingIdentity(ident);
}
{namespace_with_flags.namespace}_is_cached = true;
}
{{ endfor- }}
{{ -for flag in flag_elements }}
@Override
public boolean {flag.method_name}() \{
if (!{flag.device_config_namespace}_is_cached) \{
load_overrides_{flag.device_config_namespace}();
}
return {flag.method_name};
}
{{ endfor }}
}
{{ -endif- }} {#- end exported mode #}
{{ else }} {#- else for allow_instrumentation is not enabled #}
{{ if not library_exported- }}
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
{{ -endif }}
{{ -if runtime_lookup_required }}
import android.os.Binder;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
{{ -endif }}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
{{ -for namespace_with_flags in namespace_flags }}
private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
{{ -endfor- }}
{{ for flag in flag_elements }}
{{- if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
{{ -endif }}
{{ -endfor }}
{{ for namespace_with_flags in namespace_flags }}
private void load_overrides_{namespace_with_flags.namespace}() \{
final long ident = Binder.clearCallingIdentity();
try \{
Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
{{ -for flag in namespace_with_flags.flags }}
{{ -if flag.is_read_write }}
{flag.method_name} =
properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
{{ -endif }}
{{ -endfor }}
} catch (NullPointerException e) \{
throw new RuntimeException(
"Cannot read value from namespace {namespace_with_flags.namespace} "
+ "from DeviceConfig. It could be that the code using flag "
+ "executed before SettingsProvider initialization. Please use "
+ "fixed read-only flag by adding is_fixed_read_only: true in "
+ "flag declaration.",
e
);
} finally \{
Binder.restoreCallingIdentity(ident);
}
{namespace_with_flags.namespace}_is_cached = true;
}
{{ endfor- }}
{{ -endif }}{#- end of runtime_lookup_required #}
{{ -for flag in flag_elements }}
@Override
{{ -if not library_exported }}
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
{{ -endif }}
public boolean {flag.method_name}() \{
{{ -if flag.is_read_write }}
if (!{flag.device_config_namespace}_is_cached) \{
load_overrides_{flag.device_config_namespace}();
}
return {flag.method_name};
{{ -else }}
return {flag.default_value};
{{ -endif }}
}
{{ endfor }}
}
{{ endif}} {#- endif for allow_instrumentation #}
{{ else }} {#- Generate only stub if in test mode #}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ for flag in flag_elements }}
@Override
{{ -if not library_exported }}
@com.android.aconfig.annotations.AconfigFlagAccessor
{{ -endif }}
public boolean {flag.method_name}() \{
throw new UnsupportedOperationException(
"Method is not implemented.");
}
{{ endfor- }}
}
{{ endif }}