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