Merge "aconfig: throw exception if reading from DeviceConfig fails" into main
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index 23e2cd8..702ef22 100644
--- a/tools/aconfig/src/codegen_java.rs
+++ b/tools/aconfig/src/codegen_java.rs
@@ -177,23 +177,23 @@
         }
         @Override
         public boolean disabledRo() {
-            return getFlag(Flags.FLAG_DISABLED_RO);
+            return getValue(Flags.FLAG_DISABLED_RO);
         }
         @Override
         public boolean disabledRw() {
-            return getFlag(Flags.FLAG_DISABLED_RW);
+            return getValue(Flags.FLAG_DISABLED_RW);
         }
         @Override
         public boolean enabledFixedRo() {
-            return getFlag(Flags.FLAG_ENABLED_FIXED_RO);
+            return getValue(Flags.FLAG_ENABLED_FIXED_RO);
         }
         @Override
         public boolean enabledRo() {
-            return getFlag(Flags.FLAG_ENABLED_RO);
+            return getValue(Flags.FLAG_ENABLED_RO);
         }
         @Override
         public boolean enabledRw() {
-            return getFlag(Flags.FLAG_ENABLED_RW);
+            return getValue(Flags.FLAG_ENABLED_RW);
         }
         public void setFlag(String flagName, boolean value) {
             if (!this.mFlagMap.containsKey(flagName)) {
@@ -206,7 +206,7 @@
                 entry.setValue(null);
             }
         }
-        private boolean getFlag(String flagName) {
+        private boolean getValue(String flagName) {
             Boolean value = this.mFlagMap.get(flagName);
             if (value == null) {
                 throw new IllegalArgumentException(flagName + " is not set");
@@ -250,7 +250,7 @@
             }
             @Override
             public boolean disabledRw() {
-                return DeviceConfig.getBoolean(
+                return getValue(
                     "aconfig_test",
                     "com.android.aconfig.test.disabled_rw",
                     false
@@ -266,12 +266,33 @@
             }
             @Override
             public boolean enabledRw() {
-                return DeviceConfig.getBoolean(
+                return getValue(
                     "aconfig_test",
                     "com.android.aconfig.test.enabled_rw",
                     true
                 );
             }
+            private boolean getValue(String nameSpace,
+                String flagName, boolean defaultValue) {
+                boolean value = defaultValue;
+                try {
+                    value = DeviceConfig.getBoolean(
+                        nameSpace,
+                        flagName,
+                        defaultValue
+                    );
+                } catch (NullPointerException e) {
+                    throw new RuntimeException(
+                        "Cannot read value of flag " + flagName + " 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
+                    );
+                }
+                return value;
+            }
         }
         "#;
         let mut file_set = HashMap::from([
diff --git a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
index d4283d3..e4a1fb7 100644
--- a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
@@ -12,7 +12,7 @@
 {{ for item in class_elements}}
     @Override
     public boolean {item.method_name}() \{
-        return getFlag(Flags.FLAG_{item.flag_name_constant_suffix});
+        return getValue(Flags.FLAG_{item.flag_name_constant_suffix});
     }
 {{ endfor}}
     public void setFlag(String flagName, boolean value) \{
@@ -28,7 +28,7 @@
         }
     }
 
-    private boolean getFlag(String flagName) \{
+    private boolean getValue(String flagName) \{
         Boolean value = this.mFlagMap.get(flagName);
         if (value == null) \{
             throw new IllegalArgumentException(flagName + " is not set");
diff --git a/tools/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/templates/FeatureFlagsImpl.java.template
index 1736af9..3913fa4 100644
--- a/tools/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -9,7 +9,7 @@
     @Override
     public boolean {item.method_name}() \{
     {{ -if item.is_read_write }}
-        return DeviceConfig.getBoolean(
+        return getValue(
             "{item.device_config_namespace}",
             "{item.device_config_flag}",
             {item.default_value}
@@ -19,6 +19,29 @@
     {{ endif- }}
     }
 {{ endfor }}
+{{ if is_read_write- }}
+    private boolean getValue(String nameSpace,
+        String flagName, boolean defaultValue) \{
+        boolean value = defaultValue;
+        try \{
+            value = DeviceConfig.getBoolean(
+                nameSpace,
+                flagName,
+                defaultValue
+            );
+        } catch (NullPointerException e) \{
+            throw new RuntimeException(
+                "Cannot read value of flag " + flagName + " 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
+            );
+        }
+        return value;
+    }
+{{ endif- }}
 }
 {{ else }}
 {#- Generate only stub if in test mode #}