Add a method to get all compile-time available system features

This method is really only useful for SystemConfig, where we currently
parse available/unavailable features from the image. The method
lets us seed the SystemConfig available feature set with those defined
and compiled into the framework.

Flag: EXEMPT tool update
Test: atest systemfeatures-gen-tests systemfeatures-gen-golden-tests
Bug: 203143243
Change-Id: I627464b5a9d50137270d5658f7c4ca6b1d1f8cfe
diff --git a/tools/systemfeatures/tests/golden/RoFeatures.java.gen b/tools/systemfeatures/tests/golden/RoFeatures.java.gen
index dfc2937..edbfc42 100644
--- a/tools/systemfeatures/tests/golden/RoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RoFeatures.java.gen
@@ -8,11 +8,15 @@
 //            --feature-apis=WATCH,PC
 package com.android.systemfeatures;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
 import com.android.aconfig.annotations.AssumeFalseForR8;
 import com.android.aconfig.annotations.AssumeTrueForR8;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @hide
@@ -83,4 +87,22 @@
         }
         return null;
     }
+
+    /**
+     * Gets features marked as available at compile-time, keyed by name.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+        Map<String, FeatureInfo> features = new HashMap<>(2);
+        FeatureInfo fi = new FeatureInfo();
+        fi.name = PackageManager.FEATURE_WATCH;
+        fi.version = 1;
+        features.put(fi.name, new FeatureInfo(fi));
+        fi.name = PackageManager.FEATURE_WIFI;
+        fi.version = 0;
+        features.put(fi.name, new FeatureInfo(fi));
+        return features;
+    }
 }
diff --git a/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen b/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
index 59c5b4e..bf7a006 100644
--- a/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
@@ -4,9 +4,13 @@
 //            --feature-apis=WATCH
 package com.android.systemfeatures;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @hide
@@ -32,4 +36,15 @@
     public static Boolean maybeHasFeature(String featureName, int version) {
         return null;
     }
+
+    /**
+     * Gets features marked as available at compile-time, keyed by name.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+        Map<String, FeatureInfo> features = new HashMap<>(0);
+        return features;
+    }
 }
diff --git a/tools/systemfeatures/tests/golden/RwFeatures.java.gen b/tools/systemfeatures/tests/golden/RwFeatures.java.gen
index 89097fb..b20b228 100644
--- a/tools/systemfeatures/tests/golden/RwFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RwFeatures.java.gen
@@ -7,9 +7,13 @@
 //            --feature=AUTO:
 package com.android.systemfeatures;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @hide
@@ -62,4 +66,15 @@
     public static Boolean maybeHasFeature(String featureName, int version) {
         return null;
     }
+
+    /**
+     * Gets features marked as available at compile-time, keyed by name.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+        Map<String, FeatureInfo> features = new HashMap<>(0);
+        return features;
+    }
 }
diff --git a/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen b/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
index 2111d56..d91f5b6 100644
--- a/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
@@ -3,8 +3,12 @@
 //            --readonly=false
 package com.android.systemfeatures;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.FeatureInfo;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @hide
@@ -21,4 +25,15 @@
     public static Boolean maybeHasFeature(String featureName, int version) {
         return null;
     }
+
+    /**
+     * Gets features marked as available at compile-time, keyed by name.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Map<String, FeatureInfo> getCompileTimeAvailableFeatures() {
+        Map<String, FeatureInfo> features = new HashMap<>(0);
+        return features;
+    }
 }
diff --git a/tools/systemfeatures/tests/src/FeatureInfo.java b/tools/systemfeatures/tests/src/FeatureInfo.java
new file mode 100644
index 0000000..9d57edc
--- /dev/null
+++ b/tools/systemfeatures/tests/src/FeatureInfo.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+/** Stub for testing */
+public final class FeatureInfo {
+    public String name;
+    public int version;
+
+    public FeatureInfo() {}
+
+    public FeatureInfo(FeatureInfo orig) {
+        name = orig.name;
+        version = orig.version;
+    }
+}
diff --git a/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java b/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
index c3a23cb..39f8fc4 100644
--- a/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
+++ b/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
 
 import org.junit.Before;
@@ -36,6 +37,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.Map;
+
 @RunWith(JUnit4.class)
 public class SystemFeaturesGeneratorTest {
 
@@ -57,6 +60,7 @@
         assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
         assertThat(RwNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
         assertThat(RwNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+        assertThat(RwNoFeatures.getCompileTimeAvailableFeatures()).isEmpty();
     }
 
     @Test
@@ -68,6 +72,7 @@
         assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
         assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
         assertThat(RoNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+        assertThat(RoNoFeatures.getCompileTimeAvailableFeatures()).isEmpty();
 
         // Also ensure we fall back to the PackageManager for feature APIs without an accompanying
         // versioned feature definition.
@@ -101,6 +106,7 @@
         assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
         assertThat(RwFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
         assertThat(RwFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+        assertThat(RwFeatures.getCompileTimeAvailableFeatures()).isEmpty();
     }
 
     @Test
@@ -156,5 +162,11 @@
         assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
         assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 100)).isNull();
         assertThat(RoFeatures.maybeHasFeature("", 0)).isNull();
+
+        Map<String, FeatureInfo> compiledFeatures = RoFeatures.getCompileTimeAvailableFeatures();
+        assertThat(compiledFeatures.keySet())
+                .containsExactly(PackageManager.FEATURE_WATCH, PackageManager.FEATURE_WIFI);
+        assertThat(compiledFeatures.get(PackageManager.FEATURE_WATCH).version).isEqualTo(1);
+        assertThat(compiledFeatures.get(PackageManager.FEATURE_WIFI).version).isEqualTo(0);
     }
 }