diff options
author | 2022-02-20 12:51:03 +0000 | |
---|---|---|
committer | 2022-04-06 23:53:01 +0000 | |
commit | 9fc61018e915e3474a860585dcac290fafd262bc (patch) | |
tree | 67e374bbc39096240b71b56d7d70bcaf11047e37 | |
parent | 92713f8afeecf4dd2ce7f68733b26c24eef91ce8 (diff) |
Add custom lint check for Safety Center config
Test: atest ConfigLintCheckerTest --host
Test: m out/soong/.intermediates/packages/modules/Permission/SafetyCenter/Resources/SafetyCenterResources/android_common/lint/lint-report.html
Bug: 220722371
Change-Id: Ibbfc71f1e681bfa140e0f21c54dded59a41dd94a
12 files changed, 410 insertions, 1 deletions
diff --git a/SafetyCenter/Config/Android.bp b/SafetyCenter/Config/Android.bp index afe7c380a..2b20cea0f 100644 --- a/SafetyCenter/Config/Android.bp +++ b/SafetyCenter/Config/Android.bp @@ -17,13 +17,20 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +filegroup { + name: "safetycenter-config-parser-sources", + srcs: ["java/**/*.java"], + path: "java", + visibility: ["//packages/modules/Permission/SafetyCenter/ConfigLintChecker"], +} + java_library { name: "safety-center-config", sdk_version: "module_current", min_sdk_version: "30", target_sdk_version: "32", srcs: [ - "java/**/*.java", + ":safetycenter-config-parser-sources", ], libs: [ "androidx.annotation_annotation", diff --git a/SafetyCenter/ConfigLintChecker/Android.bp b/SafetyCenter/ConfigLintChecker/Android.bp new file mode 100644 index 000000000..4b5053f19 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/Android.bp @@ -0,0 +1,53 @@ +// Copyright (C) 2022 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +java_library_host { + name: "ConfigLintChecker", + srcs: [ + "java/**/*.java", + "java/**/*.kt", + ":safetycenter-config-api-sources", + ":safetycenter-config-parser-sources", + ], + plugins: ["auto_service_plugin"], + libs: [ + "androidx.annotation_annotation", // For androidx.annotation.RequiresApi + "auto_service_annotations", + "core-xml-for-host", // For org.xmlpull.v1.* + "framework-annotations-lib", // For com.android.annotation.* + "layoutlib_api-prebuilt", // For com.android.resources.ResourceFolderType + "lint_api", + ], + jarjar_rules: "jarjar-rules.txt", +} + +java_test_host { + name: "ConfigLintCheckerTest", + srcs: [ + "tests/java/**/*.kt", + ], + static_libs: [ + "ConfigLintChecker", + "junit", + "lint", + "lint_tests", + ], + test_options: { + unit_test: true, + }, +} diff --git a/SafetyCenter/ConfigLintChecker/jarjar-rules.txt b/SafetyCenter/ConfigLintChecker/jarjar-rules.txt new file mode 100644 index 000000000..c4a25fe33 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/jarjar-rules.txt @@ -0,0 +1,10 @@ +# Android Lint has its own API versioning and API release process. +# To check that a custom linter can be plugged into the linter execution, Android Lint inspects the +# library and makes sure that all *relevant* references can be resolved, even if they are not used +# at runtime. The assumption is that if a *relevant* reference is missing, then it must mean that +# the custom linter is using either unreleased or abandoned versions of the Android Lint APIs. +# At the time of writing, almost anything that starts with `com.android` is considered a *relevant* +# reference by `LintJarVerifier`. To work around this, preserve the dynamically linked Android Lint +# API references and rename any other `com.android` reference. +rule com.android.tools.lint.** @0 +rule com.android.** android.safetycenter.lint.jarjar.@0 diff --git a/SafetyCenter/ConfigLintChecker/java/android/content/res/Resources.java b/SafetyCenter/ConfigLintChecker/java/android/content/res/Resources.java new file mode 100644 index 000000000..8dff0a4ae --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/content/res/Resources.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 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.res; + +/** Stub class to compile the linter for host execution. */ +public final class Resources { + /** Constant used in the Safety Center config parser. */ + public static final int ID_NULL = 0; + + /** Class used in the Safety Center config parser. */ + public Resources() {} + + /** Method used in the Safety Center config parser. */ + public int getIdentifier(String name, String defType, String defPackage) { + return ID_NULL + 1; + } +} diff --git a/SafetyCenter/ConfigLintChecker/java/android/os/Build.java b/SafetyCenter/ConfigLintChecker/java/android/os/Build.java new file mode 100644 index 000000000..abe5d49d3 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/os/Build.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 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.os; + +/** Stub class to compile the linter for host execution. */ +public final class Build { + private Build() {} + + /** Stub class to used in the Safety Center config files. */ + public static final class VERSION_CODES { + /** Constant used in the Safety Center config files. */ + public static final int TIRAMISU = 10000; + } +} diff --git a/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java b/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java new file mode 100644 index 000000000..e1300de32 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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.os; + +import java.util.ArrayList; +import java.util.List; + +/** Stub interface to compile the linter for host execution. */ +public interface Parcel { + /** Method used in the Safety Center config data structures. */ + <T> ArrayList<T> createTypedArrayList(Parcelable.Creator<T> creator); + /** Method used in the Safety Center config data structures. */ + boolean readBoolean(); + /** Method used in the Safety Center config data structures. */ + int readInt(); + /** Method used in the Safety Center config data structures. */ + String readString(); + + /** Method used in the Safety Center config data structures. */ + void writeBoolean(boolean value); + /** Method used in the Safety Center config data structures. */ + void writeInt(int value); + /** Method used in the Safety Center config data structures. */ + void writeString(String value); + /** Method used in the Safety Center config data structures. */ + <T extends Parcelable> void writeTypedList(List<T> value); +} diff --git a/SafetyCenter/ConfigLintChecker/java/android/os/Parcelable.java b/SafetyCenter/ConfigLintChecker/java/android/os/Parcelable.java new file mode 100644 index 000000000..3c0cd3e70 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/os/Parcelable.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 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.os; + +/** Stub interface to compile the linter for host execution. */ +public interface Parcelable { + /** Method used in the Safety Center config data structures. */ + int describeContents(); + /** Method used in the Safety Center config data structures. */ + void writeToParcel(Parcel dest, int flags); + + /** + * Interface implemented in the Safety Center config data structures. + * + * @param <T> Generic object, should be Parcelable. + */ + interface Creator<T> { + /** Method used in the Safety Center config data structures. */ + T createFromParcel(Parcel source); + /** Method used in the Safety Center config data structures. */ + T[] newArray(int size); + } +} diff --git a/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt new file mode 100644 index 000000000..536769160 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 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.safetycenter.lint + +import com.android.tools.lint.client.api.IssueRegistry +import com.android.tools.lint.client.api.Vendor +import com.android.tools.lint.detector.api.CURRENT_API +import com.google.auto.service.AutoService + +@AutoService(IssueRegistry::class) +@Suppress("UnstableApiUsage") +class ConfigLintCheckerIssueRegistry : IssueRegistry() { + override val issues = listOf( + ParserExceptionDetector.ISSUE + ) + + override val api: Int + get() = CURRENT_API + + override val minApi: Int + get() = 11 + + override val vendor = Vendor( + vendorName = "Android", + feedbackUrl = "http://b/issues/new?component=1026964", + contact = "fiscella@google.com" + ) +} diff --git a/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ParserExceptionDetector.kt b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ParserExceptionDetector.kt new file mode 100644 index 000000000..f9cb62a8f --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ParserExceptionDetector.kt @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 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.safetycenter.lint + +import android.content.res.Resources +import com.android.resources.ResourceFolderType +import com.android.safetycenter.config.ParseException +import com.android.safetycenter.config.SafetyCenterConfigParser +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.Location +import com.android.tools.lint.detector.api.OtherFileScanner +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity + +/** Lint check for detecting invalid Safety Center configs */ +class ParserExceptionDetector : Detector(), OtherFileScanner { + + companion object { + val ISSUE = Issue.create( + id = "InvalidSafetyCenterConfig", + briefDescription = "The Safety Center config parser detected an error", + explanation = """The Safety Center config must follow all constraints defined in \ + safety_center_config.xsd. Check the error message to find out the specific \ + constraint not met by the current config.""", + category = Category.CORRECTNESS, + severity = Severity.ERROR, + implementation = Implementation( + ParserExceptionDetector::class.java, + Scope.OTHER_SCOPE + ), + androidSpecific = true + ) + } + + override fun appliesTo(folderType: ResourceFolderType): Boolean { + return folderType == ResourceFolderType.RAW + } + + override fun run(context: Context) { + if (context.file.name != "safety_center_config.xml") { + return + } + try { + SafetyCenterConfigParser.parseXmlResource(context.file.inputStream(), Resources()) + } catch (e: ParseException) { + context.report( + ISSUE, + Location.create(context.file), + "Parser exception: \"${e.message}\", cause: \"${e.cause?.message}\"" + ) + } + } +}
\ No newline at end of file diff --git a/SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ParserExceptionDetectorTest.kt b/SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ParserExceptionDetectorTest.kt new file mode 100644 index 000000000..8c859ae1d --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ParserExceptionDetectorTest.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 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.safetycenter.lint.test + +import android.safetycenter.lint.ParserExceptionDetector +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@Suppress("UnstableApiUsage") +@RunWith(JUnit4::class) +class ParserExceptionDetectorTest : LintDetectorTest() { + override fun getDetector(): Detector = ParserExceptionDetector() + + override fun getIssues(): List<Issue> = listOf(ParserExceptionDetector.ISSUE) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + @Test + fun validConfig_doesNotThrow() { + lint().files(( + xml("res/raw/safety_center_config.xml", + """ +<safety-center-config> + <safety-sources-config> + <safety-sources-group + id="group" + title="@package:string/reference" + summary="@package:string/reference"> + <static-safety-source + id="source" + title="@package:string/reference" + summary="@package:string/reference" + intentAction="intent" + profile="primary_profile_only"/> + </safety-sources-group> + </safety-sources-config> +</safety-center-config> + """))).run().expectClean() + } + + @Test + fun invalidConfig_throws() { + lint().files((xml("res/raw/safety_center_config.xml", "<invalid-root/>"))) + .run().expect("res/raw/safety_center_config.xml: Error: Parser exception: " + + "\"Element safety-center-config missing\", cause: \"null\" " + + "[InvalidSafetyCenterConfig]\n1 errors, 0 warnings") + } + + @Test + fun unrelatedFile_doesNotThrow() { + lint().files((xml("res/raw/some_other_config.xml", "<some-other-root/>"))) + .run().expectClean() + } + + @Test + fun unrelatedFolder_doesNotThrow() { + lint().files((xml("res/values/strings.xml", "<some-other-root/>"))) + .run().expectClean() + } +} diff --git a/SafetyCenter/Resources/Android.bp b/SafetyCenter/Resources/Android.bp index de6a2cab0..05f9f4c37 100644 --- a/SafetyCenter/Resources/Android.bp +++ b/SafetyCenter/Resources/Android.bp @@ -27,6 +27,9 @@ android_app { target_sdk_version: "32", apex_available: ["com.android.permission"], certificate: ":com.android.safetycenter.resources.certificate", + lint: { + extra_check_modules: ["ConfigLintChecker"], + }, } android_app_certificate { diff --git a/framework-s/Android.bp b/framework-s/Android.bp index 9d93799a2..6be71d416 100644 --- a/framework-s/Android.bp +++ b/framework-s/Android.bp @@ -26,6 +26,13 @@ filegroup { visibility: ["//frameworks/base"], } +filegroup { + name: "safetycenter-config-api-sources", + srcs: ["java/android/safetycenter/config/*.java"], + path: "java", + visibility: ["//packages/modules/Permission/SafetyCenter/ConfigLintChecker"], +} + java_library { name: "framework-permission-s-shared", srcs: [":framework-permission-s-shared-srcs"], |