Merge "Add SystemFeaturesMetadataPerfTest" into main
diff --git a/apct-tests/perftests/core/src/android/content/pm/SystemFeaturesMetadataPerfTest.java b/apct-tests/perftests/core/src/android/content/pm/SystemFeaturesMetadataPerfTest.java
new file mode 100644
index 0000000..205c7b8
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/content/pm/SystemFeaturesMetadataPerfTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class SystemFeaturesMetadataPerfTest {
+    // As each query is relatively cheap, add an inner iteration loop to reduce execution noise.
+    private static final int NUM_ITERATIONS = 10;
+
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void maybeGetSdkFeatureIndex_featureDefined() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < NUM_ITERATIONS; ++i) {
+                PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_WATCH);
+                PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_LEANBACK);
+                PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_IPSEC_TUNNELS);
+                PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_WEBVIEW);
+                PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_NFC_BEAM);
+                PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_AUTOFILL);
+            }
+        }
+    }
+
+    @Test
+    public void maybeGetSdkFeatureIndex_featureUndefined() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < NUM_ITERATIONS; ++i) {
+                PackageManager.maybeGetSdkFeatureIndex("com.android.custom.feature.1");
+                PackageManager.maybeGetSdkFeatureIndex("com.android.custom.feature.2");
+                PackageManager.maybeGetSdkFeatureIndex("foo");
+                PackageManager.maybeGetSdkFeatureIndex("bar");
+                PackageManager.maybeGetSdkFeatureIndex("0");
+                PackageManager.maybeGetSdkFeatureIndex("");
+            }
+        }
+    }
+
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 07775f7..fbcefa3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3116,16 +3116,6 @@
     public static final long MAXIMUM_VERIFICATION_TIMEOUT = 60*60*1000;
 
     /**
-     * As the generated feature count is useful for classes that may not be compiled in the same
-     * annotation processing unit as PackageManager, we redeclare it here for visibility.
-     *
-     * @hide
-     */
-    @VisibleForTesting
-    public static final int SDK_FEATURE_COUNT =
-            com.android.internal.pm.SystemFeaturesMetadata.SDK_FEATURE_COUNT;
-
-    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device's
      * audio pipeline is low-latency, more suitable for audio applications sensitive to delays or
      * lag in sound input or output.
@@ -11876,4 +11866,28 @@
         }
         return new SigningInfo(result.getResult());
     }
+
+    /**
+     * As the generated feature count is useful for classes that may not be compiled in the same
+     * annotation processing unit as PackageManager, we redeclare it here for visibility.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static final int SDK_FEATURE_COUNT =
+            com.android.internal.pm.SystemFeaturesMetadata.SDK_FEATURE_COUNT;
+
+    /**
+     * Returns a stable index for PackageManager-defined features.
+     *
+     * <p> Similar to {@link #SDK_FEATURE_COUNT}, we redeclare this utility method generated by the
+     * annotation processor for internal visibility.
+     *
+     * @return index in [0, {@link #SDK_FEATURECOUNT}) for PackageManager-defined features, else -1.
+     * @hide
+     */
+    @VisibleForTesting
+    public static int maybeGetSdkFeatureIndex(String featureName) {
+        return com.android.internal.pm.SystemFeaturesMetadata.maybeGetSdkFeatureIndex(featureName);
+    }
 }