Loading tools/systemfeatures/Android.bp +2 −2 Original line number Diff line number Diff line Loading @@ -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", Loading tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt +17 −12 Original line number Diff line number Diff line Loading @@ -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> * Loading @@ -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); * } Loading @@ -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") Loading @@ -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>() Loading Loading @@ -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 Loading Loading @@ -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 = Loading Loading @@ -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) } tools/systemfeatures/tests/golden/RoFeatures.java.gen +3 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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; Loading tools/systemfeatures/tests/golden/RwFeatures.java.gen +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ // --readonly=false \ // --feature=WATCH:1 \ // --feature=WIFI:0 \ // --feature=VULKAN:-1 \ // --feature=VULKAN:UNAVAILABLE \ // --feature=AUTO: package com.android.systemfeatures; Loading tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java +16 −8 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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. Loading @@ -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(); } } Loading
tools/systemfeatures/Android.bp +2 −2 Original line number Diff line number Diff line Loading @@ -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", Loading
tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt +17 −12 Original line number Diff line number Diff line Loading @@ -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> * Loading @@ -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); * } Loading @@ -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") Loading @@ -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>() Loading Loading @@ -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 Loading Loading @@ -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 = Loading Loading @@ -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) }
tools/systemfeatures/tests/golden/RoFeatures.java.gen +3 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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; Loading
tools/systemfeatures/tests/golden/RwFeatures.java.gen +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ // --readonly=false \ // --feature=WATCH:1 \ // --feature=WIFI:0 \ // --feature=VULKAN:-1 \ // --feature=VULKAN:UNAVAILABLE \ // --feature=AUTO: package com.android.systemfeatures; Loading
tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java +16 −8 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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. Loading @@ -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(); } }