diff options
Diffstat (limited to 'tools')
11 files changed, 143 insertions, 48 deletions
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt index c3595b7ac288..272d8bb1793d 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt @@ -119,7 +119,8 @@ class ProtoLogCallProcessorImpl( } logCallVisitor?.processCall(call, messageString, getLevelForMethodName( - call.name.toString(), call, context), groupMap.getValue(groupName)) + call.name.toString(), call, context), groupMap.getValue(groupName), + context.lineNumber) } else if (call.name.id == "init") { // No processing } else { diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt index 8cd927a7cd0e..216241ac5a47 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallVisitor.kt @@ -20,5 +20,11 @@ import com.android.internal.protolog.common.LogLevel import com.github.javaparser.ast.expr.MethodCallExpr interface ProtoLogCallVisitor { - fun processCall(call: MethodCallExpr, messageString: String, level: LogLevel, group: LogGroup) + fun processCall( + call: MethodCallExpr, + messageString: String, + level: LogLevel, + group: LogGroup, + lineNumber: Int + ) } diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt index 9222ff4bf52c..d8a2954545bb 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt @@ -69,7 +69,8 @@ object ProtoLogTool { val messageString: String, val logLevel: LogLevel, val logGroup: LogGroup, - val position: String + val position: String, + val lineNumber: Int, ) private fun showHelpAndExit() { @@ -435,9 +436,10 @@ object ProtoLogTool { call: MethodCallExpr, messageString: String, level: LogLevel, - group: LogGroup + group: LogGroup, + lineNumber: Int, ) { - val logCall = LogCall(messageString, level, group, packagePath) + val logCall = LogCall(messageString, level, group, packagePath, lineNumber) calls.add(logCall) } } diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt index c478f5844de6..76df0674df65 100644 --- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt +++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt @@ -91,7 +91,8 @@ class SourceTransformer( call: MethodCallExpr, messageString: String, level: LogLevel, - group: LogGroup + group: LogGroup, + lineNumber: Int, ) { validateCall(call) val processedCallStatement = diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt index de85411e4ffc..5af2d9440533 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt @@ -59,7 +59,7 @@ class ViewerConfigProtoBuilder : ProtoLogTool.ProtologViewerConfigBuilder { .setLevel( ProtoLogLevel.forNumber(log.logLevel.id)) .setGroupId(groupId) - .setLocation(log.position) + .setLocation("${log.position}:${log.lineNumber}") ) } diff --git a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorImplTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorImplTest.kt index 5e50f71d75cc..004d97babbad 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorImplTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogCallProcessorImplTest.kt @@ -42,7 +42,8 @@ class ProtoLogCallProcessorImplTest { call: MethodCallExpr, messageString: String, level: LogLevel, - group: LogGroup + group: LogGroup, + lineNumber: Int, ) { calls.add(LogCall(call, messageString, level, group)) } diff --git a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt index 6cde7a72db53..674a907d68d9 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt @@ -158,7 +158,7 @@ class SourceTransformerTest { val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f", - LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST")) + LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST"), 123) invocation.arguments[0] as CompilationUnit } @@ -195,11 +195,11 @@ class SourceTransformerTest { val calls = code.findAll(MethodCallExpr::class.java) visitor.processCall(calls[0], "test %d %f", - LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST")) + LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST"), 456) visitor.processCall(calls[1], "test %d %f", - LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST")) + LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST"), 789) visitor.processCall(calls[2], "test %d %f", - LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST")) + LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST"), 123) invocation.arguments[0] as CompilationUnit } @@ -236,7 +236,7 @@ class SourceTransformerTest { visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f abc %s\n test", LogLevel.WARN, LogGroup("TEST_GROUP", - true, true, "WM_TEST")) + true, true, "WM_TEST"), 123) invocation.arguments[0] as CompilationUnit } @@ -273,7 +273,7 @@ class SourceTransformerTest { val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test", - LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST")) + LogLevel.WARN, LogGroup("TEST_GROUP", true, true, "WM_TEST"), 456) invocation.arguments[0] as CompilationUnit } @@ -307,7 +307,7 @@ class SourceTransformerTest { val visitor = invocation.arguments[1] as ProtoLogCallVisitor visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f", - LogLevel.WARN, LogGroup("TEST_GROUP", true, false, "WM_TEST")) + LogLevel.WARN, LogGroup("TEST_GROUP", true, false, "WM_TEST"), 789) invocation.arguments[0] as CompilationUnit } @@ -344,7 +344,7 @@ class SourceTransformerTest { visitor.processCall(code.findAll(MethodCallExpr::class.java)[0], "test %d %f abc %s\n test", LogLevel.WARN, LogGroup("TEST_GROUP", - true, false, "WM_TEST")) + true, false, "WM_TEST"), 123) invocation.arguments[0] as CompilationUnit } diff --git a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigJsonBuilderTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigJsonBuilderTest.kt index 1a20d4c5bad6..bcbc8790e170 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigJsonBuilderTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigJsonBuilderTest.kt @@ -50,9 +50,9 @@ class ViewerConfigJsonBuilderTest { fun processClass() { val logCallRegistry = ProtoLogTool.LogCallRegistry() logCallRegistry.addLogCalls(listOf( - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), - LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP2, PATH), - LogCall(TEST3.messageString, LogLevel.ERROR, GROUP3, PATH))) + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH, 123), + LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP2, PATH, 456), + LogCall(TEST3.messageString, LogLevel.ERROR, GROUP3, PATH, 789))) val parsedConfig = parseConfig( configBuilder.build(GROUPS, logCallRegistry.getStatements()).toString(Charsets.UTF_8)) @@ -69,9 +69,9 @@ class ViewerConfigJsonBuilderTest { fun processClass_nonUnique() { val logCallRegistry = ProtoLogTool.LogCallRegistry() logCallRegistry.addLogCalls(listOf( - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH))) + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH, 123), + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH, 456), + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH, 789))) val parsedConfig = parseConfig( configBuilder.build(GROUPS, logCallRegistry.getStatements()).toString(Charsets.UTF_8)) diff --git a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigProtoBuilderTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigProtoBuilderTest.kt index 74a8de7f70c0..dfc66405eec9 100644 --- a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigProtoBuilderTest.kt +++ b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigProtoBuilderTest.kt @@ -55,8 +55,8 @@ class ViewerConfigProtoBuilderTest { val logCallRegistry = ProtoLogTool.LogCallRegistry() logCallRegistry.addLogCalls(listOf( - LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH), - LogCall(TEST2.messageString, LogLevel.INFO, GROUP2, PATH), + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH, 123), + LogCall(TEST2.messageString, LogLevel.INFO, GROUP2, PATH, 456), )) val rawProto = configBuilder.build(GROUPS, logCallRegistry.getStatements()) @@ -65,4 +65,22 @@ class ViewerConfigProtoBuilderTest { Truth.assertThat(viewerConfig.groupsCount).isEqualTo(GROUPS.size) Truth.assertThat(viewerConfig.messagesCount).isLessThan(GROUPS.size) } + + @Test + fun includesLineNumberInLocation() { + val configBuilder = ViewerConfigProtoBuilder() + + val logCallRegistry = ProtoLogTool.LogCallRegistry() + logCallRegistry.addLogCalls(listOf( + LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH, 123), + LogCall(TEST2.messageString, LogLevel.INFO, GROUP2, PATH, 456), + )) + + val rawProto = configBuilder.build(GROUPS, logCallRegistry.getStatements()) + + val viewerConfig = ProtoLogViewerConfig.parseFrom(rawProto) + + Truth.assertThat(viewerConfig.messagesList[0].location).isEqualTo("$PATH:123") + Truth.assertThat(viewerConfig.messagesList[1].location).isEqualTo("$PATH:456") + } }
\ No newline at end of file diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt index 4a6d4b1f49ef..c51c6d661314 100644 --- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt +++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt @@ -18,9 +18,11 @@ package com.android.systemfeatures import android.annotation.SdkConstant import com.squareup.javapoet.ClassName +import com.squareup.javapoet.CodeBlock import com.squareup.javapoet.FieldSpec import com.squareup.javapoet.JavaFile import com.squareup.javapoet.MethodSpec +import com.squareup.javapoet.ParameterizedTypeName import com.squareup.javapoet.TypeSpec import java.io.IOException import javax.annotation.processing.AbstractProcessor @@ -101,8 +103,8 @@ class SystemFeaturesMetadataProcessor : AbstractProcessor() { TypeSpec.classBuilder("SystemFeaturesMetadata") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addJavadoc("@hide") - .addField(buildFeatureCount(featureVarNames)) - .addMethod(buildFeatureIndexLookup(featureVarNames)) + .addFeatureCount(featureVarNames) + .addFeatureIndexLookup(featureVarNames) .build() try { @@ -120,19 +122,55 @@ class SystemFeaturesMetadataProcessor : AbstractProcessor() { return true } - private fun buildFeatureCount(featureVarNames: Collection<String>): FieldSpec { - return FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .addJavadoc( - "# of {@link android.annotation.SdkConstant}` features defined in PackageManager." - ) - .addJavadoc("\n\n@hide") - .initializer("\$L", featureVarNames.size) - .build() + private fun TypeSpec.Builder.addFeatureCount( + featureVarNames: Collection<String> + ): TypeSpec.Builder { + return addField( + FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .addJavadoc( + "# of {@link android.annotation.SdkConstant}` features in PackageManager." + ) + .addJavadoc("\n\n@hide") + .initializer("\$L", featureVarNames.size) + .build() + ) } - private fun buildFeatureIndexLookup(featureVarNames: Collection<String>): MethodSpec { - val methodBuilder = + private fun TypeSpec.Builder.addFeatureIndexLookup( + featureVarNames: Collection<String> + ): TypeSpec.Builder { + // NOTE: This was initially implemented in terms of a single, long switch() statement. + // However, this resulted in: + // 1) relatively large compiled code size for the lookup method (~20KB) + // 2) worse runtime lookup performance than a simple ArraySet + // The ArraySet approach adds just ~1KB to the code/image and is 2x faster at runtime. + + // Provide the initial capacity of the ArraySet for efficiency. + addField( + FieldSpec.builder( + ParameterizedTypeName.get(ARRAYSET_CLASS, ClassName.get(String::class.java)), + "sFeatures", + ) + .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .initializer("new ArraySet<>(\$L)", featureVarNames.size) + .build() + ) + + // Use a temp array + Collections.addAll() to minimizes the generated code size. + addStaticBlock( + CodeBlock.builder() + .add("final \$T[] features = {\n", String::class.java) + .indent() + .apply { featureVarNames.forEach { add("\$T.\$N,\n", PACKAGEMANAGER_CLASS, it) } } + .unindent() + .addStatement("}") + .addStatement("\$T.addAll(sFeatures, features)", COLLECTIONS_CLASS) + .build() + ) + + // Use ArraySet.indexOf to provide the implicit feature index mapping. + return addMethod( MethodSpec.methodBuilder("maybeGetSdkFeatureIndex") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addJavadoc("@return an index in [0, SDK_FEATURE_COUNT) for features defined ") @@ -140,21 +178,15 @@ class SystemFeaturesMetadataProcessor : AbstractProcessor() { .addJavadoc("\n\n@hide") .returns(Int::class.java) .addParameter(String::class.java, "featureName") - methodBuilder.beginControlFlow("switch (featureName)") - featureVarNames.forEachIndexed { index, featureVarName -> - methodBuilder - .addCode("case \$T.\$N: ", PACKAGEMANAGER_CLASS, featureVarName) - .addStatement("return \$L", index) - } - methodBuilder - .addCode("default: ") - .addStatement("return -1") - .endControlFlow() - return methodBuilder.build() + .addStatement("return sFeatures.indexOf(featureName)") + .build() + ) } companion object { private val SDK_CONSTANT_ANNOTATION_NAME = SdkConstant::class.qualifiedName private val PACKAGEMANAGER_CLASS = ClassName.get("android.content.pm", "PackageManager") + private val ARRAYSET_CLASS = ClassName.get("android.util", "ArraySet") + private val COLLECTIONS_CLASS = ClassName.get("java.util", "Collections") } } diff --git a/tools/systemfeatures/tests/src/ArraySet.java b/tools/systemfeatures/tests/src/ArraySet.java new file mode 100644 index 000000000000..0eb8f298bd89 --- /dev/null +++ b/tools/systemfeatures/tests/src/ArraySet.java @@ -0,0 +1,34 @@ +/* + * 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.util; + +import java.util.ArrayList; + +/** Stub for testing, we extend ArrayList to get indexOf() for free. */ +public final class ArraySet<K> extends ArrayList<K> { + public ArraySet(int capacity) { + super(capacity); + } + + @Override + public boolean add(K k) { + if (!contains(k)) { + return super.add(k); + } + return false; + } +} |