xref: /aosp_15_r20/build/make/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1package {package_name};
2{{ -if not is_test_mode }}
3{{ -if allow_instrumentation }}
4{{ if not library_exported- }}{#- only new storage for prod mode #}
5// TODO(b/303773055): Remove the annotation after access issue is resolved.
6import android.compat.annotation.UnsupportedAppUsage;
7{{ -if runtime_lookup_required }}
8import android.os.Build;
9{{ if is_platform_container }}
10import android.os.flagging.PlatformAconfigPackageInternal;
11{{ -else }}
12import android.os.flagging.AconfigPackageInternal;
13{{ -endif }}
14import android.util.Log;
15{{ -endif }}
16/** @hide */
17public final class FeatureFlagsImpl implements FeatureFlags \{
18{{ -if runtime_lookup_required }}
19    private static final String TAG = "{package_name}.FeatureFlagsImpl";
20    private static volatile boolean isCached = false;
21{{ for flag in flag_elements }}
22{{ -if flag.is_read_write }}
23    private static boolean {flag.method_name} = {flag.default_value};
24{{ -endif }}
25{{ -endfor }}
26
27    private void init() \{
28        try \{
29{{ if is_platform_container }}
30            PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("{container}", "{package_name}", {package_fingerprint});
31{{ -else }}
32            AconfigPackageInternal reader = AconfigPackageInternal.load("{container}", "{package_name}", {package_fingerprint});
33{{ -endif }}
34        {{ -for namespace_with_flags in namespace_flags }}
35        {{ -for flag in namespace_with_flags.flags }}
36        {{ -if flag.is_read_write }}
37            {flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
38        {{ -endif }}
39        {{ -endfor }}
40        {{ -endfor }}
41        } catch (Exception e) \{
42            Log.e(TAG, e.toString());
43        } catch (NoClassDefFoundError e) \{
44            // for mainline module running on older devices.
45            // This should be replaces to version check, after the version bump.
46            Log.e(TAG, e.toString());
47        }
48        isCached = true;
49    }
50{{ -endif }}{#- end of runtime_lookup_required #}
51{{ -for flag in flag_elements }}
52    @Override
53    @com.android.aconfig.annotations.AconfigFlagAccessor
54    @UnsupportedAppUsage
55    public boolean {flag.method_name}() \{
56{{ -if flag.is_read_write }}
57        if (!isCached) \{
58            init();
59        }
60        return {flag.method_name};
61{{ -else }}
62        return {flag.default_value};
63{{ -endif }}
64    }
65{{ endfor }}
66}
67{{ -else- }}{#- device config for exproted mode #}
68import android.os.Binder;
69import android.provider.DeviceConfig;
70import android.provider.DeviceConfig.Properties;
71/** @hide */
72public final class FeatureFlagsImpl implements FeatureFlags \{
73{{ -for namespace_with_flags in namespace_flags }}
74    private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
75{{ -endfor- }}
76{{ for flag in flag_elements }}
77{{ -if flag.is_read_write }}
78    private static boolean {flag.method_name} = {flag.default_value};
79{{ -endif }}
80{{ -endfor }}
81{{ for namespace_with_flags in namespace_flags }}
82    private void load_overrides_{namespace_with_flags.namespace}() \{
83        final long ident = Binder.clearCallingIdentity();
84        try \{
85            Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
86{{ -for flag in namespace_with_flags.flags }}
87{{ -if flag.is_read_write }}
88            {flag.method_name} =
89                properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
90{{ -endif }}
91{{ -endfor }}
92        } catch (NullPointerException e) \{
93            throw new RuntimeException(
94                "Cannot read value from namespace {namespace_with_flags.namespace} "
95                + "from DeviceConfig. It could be that the code using flag "
96                + "executed before SettingsProvider initialization. Please use "
97                + "fixed read-only flag by adding is_fixed_read_only: true in "
98                + "flag declaration.",
99                e
100            );
101        } catch (SecurityException e) \{
102            // for isolated process case, skip loading flag value from the storage, use the default
103        } finally \{
104            Binder.restoreCallingIdentity(ident);
105        }
106        {namespace_with_flags.namespace}_is_cached = true;
107    }
108{{ endfor- }}
109{{ -for flag in flag_elements }}
110    @Override
111    public boolean {flag.method_name}() \{
112        if (!{flag.device_config_namespace}_is_cached) \{
113            load_overrides_{flag.device_config_namespace}();
114        }
115        return {flag.method_name};
116    }
117{{ endfor }}
118}
119{{ -endif- }} {#- end exported mode #}
120{{ else }} {#- else for allow_instrumentation is not enabled #}
121{{ if not library_exported- }}
122// TODO(b/303773055): Remove the annotation after access issue is resolved.
123import android.compat.annotation.UnsupportedAppUsage;
124{{ -endif }}
125
126{{ -if runtime_lookup_required }}
127import android.os.Binder;
128import android.provider.DeviceConfig;
129import android.provider.DeviceConfig.Properties;
130{{ -endif }}
131/** @hide */
132public final class FeatureFlagsImpl implements FeatureFlags \{
133{{ -if runtime_lookup_required }}
134{{ -for namespace_with_flags in namespace_flags }}
135    private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
136{{ -endfor- }}
137
138{{ for flag in flag_elements }}
139{{- if flag.is_read_write }}
140    private static boolean {flag.method_name} = {flag.default_value};
141{{ -endif }}
142{{ -endfor }}
143{{ for namespace_with_flags in namespace_flags }}
144    private void load_overrides_{namespace_with_flags.namespace}() \{
145        final long ident = Binder.clearCallingIdentity();
146        try \{
147            Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
148{{ -for flag in namespace_with_flags.flags }}
149{{ -if flag.is_read_write }}
150            {flag.method_name} =
151                properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
152{{ -endif }}
153{{ -endfor }}
154        } catch (NullPointerException e) \{
155            throw new RuntimeException(
156                "Cannot read value from namespace {namespace_with_flags.namespace} "
157                + "from DeviceConfig. It could be that the code using flag "
158                + "executed before SettingsProvider initialization. Please use "
159                + "fixed read-only flag by adding is_fixed_read_only: true in "
160                + "flag declaration.",
161                e
162            );
163        } finally \{
164            Binder.restoreCallingIdentity(ident);
165        }
166        {namespace_with_flags.namespace}_is_cached = true;
167}
168{{ endfor- }}
169{{ -endif }}{#- end of runtime_lookup_required #}
170{{ -for flag in flag_elements }}
171    @Override
172{{ -if not library_exported }}
173    @com.android.aconfig.annotations.AconfigFlagAccessor
174    @UnsupportedAppUsage
175{{ -endif }}
176    public boolean {flag.method_name}() \{
177{{ -if flag.is_read_write }}
178        if (!{flag.device_config_namespace}_is_cached) \{
179            load_overrides_{flag.device_config_namespace}();
180        }
181        return {flag.method_name};
182{{ -else }}
183        return {flag.default_value};
184{{ -endif }}
185    }
186{{ endfor }}
187}
188{{ endif}} {#- endif for allow_instrumentation #}
189{{ else }} {#- Generate only stub if in test mode #}
190/** @hide */
191public final class FeatureFlagsImpl implements FeatureFlags \{
192{{ for flag in flag_elements }}
193    @Override
194{{ -if not library_exported }}
195    @com.android.aconfig.annotations.AconfigFlagAccessor
196{{ -endif }}
197    public boolean {flag.method_name}() \{
198        throw new UnsupportedOperationException(
199            "Method is not implemented.");
200    }
201{{ endfor- }}
202}
203{{ endif }}
204