Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1d0238c authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Refine systemfeature codegen behavior" into main am: e6ba96dd

parents 20757be6 e6ba96dd
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@ genrule {
    name: "systemfeatures-gen-tests-srcs",
    cmd: "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwNoFeatures --readonly=false > $(location RwNoFeatures.java) && " +
        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoNoFeatures --readonly=true --feature-apis=WATCH > $(location RoNoFeatures.java) && " +
        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwFeatures --readonly=false --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:-1 --feature=AUTO: > $(location RwFeatures.java) && " +
        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoFeatures --readonly=true --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:-1 --feature=AUTO: --feature-apis=WATCH,PC > $(location RoFeatures.java)",
        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwFeatures --readonly=false --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:UNAVAILABLE --feature=AUTO: > $(location RwFeatures.java) && " +
        "$(location systemfeatures-gen-tool) com.android.systemfeatures.RoFeatures --readonly=true --feature=WATCH:1 --feature=WIFI:0 --feature=VULKAN:UNAVAILABLE --feature=AUTO: --feature-apis=WATCH,PC > $(location RoFeatures.java)",
    out: [
        "RwNoFeatures.java",
        "RoNoFeatures.java",
+17 −12
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import javax.lang.model.element.Modifier
 *
 * <pre>
 *   <cmd> com.foo.RoSystemFeatures --readonly=true \
 *           --feature=WATCH:0 --feature=AUTOMOTIVE: --feature=VULKAN:9348
 *           --feature=WATCH:0 --feature=AUTOMOTIVE: --feature=VULKAN:9348 --feature=PC:UNAVAILABLE
 *           --feature-apis=WATCH,PC,LEANBACK
 * </pre>
 *
@@ -43,10 +43,10 @@ import javax.lang.model.element.Modifier
 *     @AssumeTrueForR8
 *     public static boolean hasFeatureWatch(Context context);
 *     @AssumeFalseForR8
 *     public static boolean hasFeatureAutomotive(Context context);
 *     public static boolean hasFeaturePc(Context context);
 *     @AssumeTrueForR8
 *     public static boolean hasFeatureVulkan(Context context);
 *     public static boolean hasFeaturePc(Context context);
 *     public static boolean hasFeatureAutomotive(Context context);
 *     public static boolean hasFeatureLeanback(Context context);
 *     public static Boolean maybeHasFeature(String feature, int version);
 * }
@@ -67,7 +67,10 @@ object SystemFeaturesGenerator {
        println("Usage: SystemFeaturesGenerator <outputClassName> [options]")
        println(" Options:")
        println("  --readonly=true|false    Whether to encode features as build-time constants")
        println("  --feature=\$NAME:\$VER   A feature+version pair (blank version == disabled)")
        println("  --feature=\$NAME:\$VER   A feature+version pair, where \$VER can be:")
        println("                             * blank/empty == undefined (variable API)")
        println("                             * valid int   == enabled   (constant API)")
        println("                             * UNAVAILABLE == disabled  (constant API)")
        println("                           This will always generate associated query APIs,")
        println("                           adding to or replacing those from `--feature-apis=`.")
        println("  --feature-apis=\$NAME_1,\$NAME_2")
@@ -89,7 +92,7 @@ object SystemFeaturesGenerator {

        var readonly = false
        var outputClassName: ClassName? = null
        val featureArgs = mutableListOf<FeatureArg>()
        val featureArgs = mutableListOf<FeatureInfo>()
        // We could just as easily hardcode this list, as the static API surface should change
        // somewhat infrequently, but this decouples the codegen from the framework completely.
        val featureApiArgs = mutableSetOf<String>()
@@ -122,7 +125,7 @@ object SystemFeaturesGenerator {
        featureArgs.associateByTo(
            features,
            { it.name },
            { FeatureInfo(it.name, it.version, readonly) },
            { FeatureInfo(it.name, it.version, it.readonly && readonly) },
        )

        outputClassName
@@ -154,13 +157,17 @@ object SystemFeaturesGenerator {
     * Parses a feature argument of the form "--feature=$NAME:$VER", where "$VER" is optional.
     *   * "--feature=WATCH:0" -> Feature enabled w/ version 0 (default version when enabled)
     *   * "--feature=WATCH:7" -> Feature enabled w/ version 7
     *   * "--feature=WATCH:"  -> Feature disabled
     *   * "--feature=WATCH:"  -> Feature status undefined, runtime API generated
     *   * "--feature=WATCH:UNAVAILABLE"  -> Feature disabled
     */
    private fun parseFeatureArg(arg: String): FeatureArg {
    private fun parseFeatureArg(arg: String): FeatureInfo {
        val featureArgs = arg.substring(FEATURE_ARG.length).split(":")
        val name = parseFeatureName(featureArgs[0])
        val version = featureArgs.getOrNull(1)?.toIntOrNull()
        return FeatureArg(name, version)
        return when (featureArgs.getOrNull(1)) {
            null, "" -> FeatureInfo(name, null, readonly = false)
            "UNAVAILABLE" -> FeatureInfo(name, null, readonly = true)
            else -> FeatureInfo(name, featureArgs[1].toIntOrNull(), readonly = true)
        }
    }

    private fun parseFeatureName(name: String): String =
@@ -267,7 +274,5 @@ object SystemFeaturesGenerator {
        builder.addMethod(methodBuilder.build())
    }

    private data class FeatureArg(val name: String, val version: Int?)

    private data class FeatureInfo(val name: String, val version: Int?, val readonly: Boolean)
}
+3 −5
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
//            --readonly=true \
//            --feature=WATCH:1 \
//            --feature=WIFI:0 \
//            --feature=VULKAN:-1 \
//            --feature=VULKAN:UNAVAILABLE \
//            --feature=AUTO: \
//            --feature-apis=WATCH,PC
package com.android.systemfeatures;
@@ -62,9 +62,8 @@ public final class RoFeatures {
     *
     * @hide
     */
    @AssumeFalseForR8
    public static boolean hasFeatureAuto(Context context) {
        return false;
        return hasFeatureFallback(context, PackageManager.FEATURE_AUTO);
    }

    private static boolean hasFeatureFallback(Context context, String featureName) {
@@ -79,8 +78,7 @@ public final class RoFeatures {
        switch (featureName) {
            case PackageManager.FEATURE_WATCH: return 1 >= version;
            case PackageManager.FEATURE_WIFI: return 0 >= version;
            case PackageManager.FEATURE_VULKAN: return -1 >= version;
            case PackageManager.FEATURE_AUTO: return false;
            case PackageManager.FEATURE_VULKAN: return false;
            default: break;
        }
        return null;
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
//            --readonly=false \
//            --feature=WATCH:1 \
//            --feature=WIFI:0 \
//            --feature=VULKAN:-1 \
//            --feature=VULKAN:UNAVAILABLE \
//            --feature=AUTO:
package com.android.systemfeatures;

+16 −8
Original line number Diff line number Diff line
@@ -110,10 +110,13 @@ public class SystemFeaturesGeneratorTest {
        assertThat(RoFeatures.hasFeatureWatch(mContext)).isTrue();
        assertThat(RoFeatures.hasFeatureWifi(mContext)).isTrue();
        assertThat(RoFeatures.hasFeatureVulkan(mContext)).isFalse();
        assertThat(RoFeatures.hasFeatureAuto(mContext)).isFalse();
        verify(mPackageManager, never()).hasSystemFeature(anyString(), anyInt());

        // For defined feature types, conditional queries should reflect the build-time versions.
        // For defined feature types, conditional queries should reflect either:
        //  * Enabled if the feature version is specified
        //  * Disabled if UNAVAILABLE is specified
        //  * Unknown if no version value is provided

        // VERSION=1
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, -1)).isTrue();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WATCH, 0)).isTrue();
@@ -124,15 +127,19 @@ public class SystemFeaturesGeneratorTest {
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 0)).isTrue();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_WIFI, 100)).isFalse();

        // VERSION=-1
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, -1)).isTrue();
        // VERSION=UNAVAILABLE
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, -1)).isFalse();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 0)).isFalse();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 100)).isFalse();

        // DISABLED
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, -1)).isFalse();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isFalse();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 100)).isFalse();
        // VERSION=
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(false);
        assertThat(RoFeatures.hasFeatureAuto(mContext)).isFalse();
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(true);
        assertThat(RoFeatures.hasFeatureAuto(mContext)).isTrue();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, -1)).isNull();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
        assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 100)).isNull();

        // For feature APIs without an associated feature definition, conditional queries should
        // report null, and explicit queries should report runtime-defined versions.
@@ -148,5 +155,6 @@ public class SystemFeaturesGeneratorTest {
        assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", -1)).isNull();
        assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 0)).isNull();
        assertThat(RoFeatures.maybeHasFeature("com.arbitrary.feature", 100)).isNull();
        assertThat(RoFeatures.maybeHasFeature("", 0)).isNull();
    }
}