Decouple system feature API codegen from feature definitions

The set of build-time, readonly features will vary for each device. To
ensure we at least have a minimal static API surface to target, allow
specifying a minimal feature API set alongside any explicitly defined
feature values.

This will let us start migrating a subset of internal hasSystemFeature
API queries to use the new API, independent of integration with the
build system and per-device build flag settings.

Initially, this will just be a passthrough API surface with no build or
runtime behavioral differences. As we integrate per-device build flags,
the (sub)set of explicitly defined features will change how each API
behaves.

Bug: 203143243
Test: atest systemfeatures-gen-tests --host
Change-Id: I3c84375bdc1a2e31cc72fa09f3b980c2daa85bb2
diff --git a/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java b/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java
index 547d2cb..6dfd244 100644
--- a/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java
+++ b/tools/systemfeatures/tests/SystemFeaturesGeneratorTest.java
@@ -68,6 +68,13 @@
         assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isNull();
         assertThat(RoNoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
         assertThat(RoNoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
+
+        // Also ensure we fall back to the PackageManager for feature APIs without an accompanying
+        // versioned feature definition.
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(true);
+        assertThat(RwFeatures.hasFeatureWatch(mContext)).isTrue();
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(false);
+        assertThat(RwFeatures.hasFeatureWatch(mContext)).isFalse();
     }
 
     @Test
@@ -127,6 +134,16 @@
         assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isFalse();
         assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 100)).isFalse();
 
+        // For feature APIs without an associated feature definition, conditional queries should
+        // report null, and explicit queries should report runtime-defined versions.
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC, 0)).thenReturn(true);
+        assertThat(RoFeatures.hasFeaturePc(mContext)).isTrue();
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC, 0)).thenReturn(false);
+        assertThat(RoFeatures.hasFeaturePc(mContext)).isFalse();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, -1)).isNull();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, 0)).isNull();
+        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, 100)).isNull();
+
         // For undefined types, conditional queries should report null (unknown).
         assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", -1)).isNull();
         assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();