From e45981741a018b6f0aeefb46f16f82a0ce627e16 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Thu, 11 Aug 2022 17:32:46 -0700 Subject: [PATCH] Hardware bitmap linter Encrouage engineers to use Config.HARDWARE instead of other types of Bitmaps. Test: atest SoftwareBitmapDetectorTest Bug: 238923086 Change-Id: I3c2e789546c137d73b8a5ec5f7ef5755144b622d --- .../systemui/lint/SoftwareBitmapDetector.kt | 72 ++++++++++++++ .../systemui/lint/SystemUIIssueRegistry.kt | 6 +- .../lint/SoftwareBitmapDetectorTest.kt | 97 +++++++++++++++++++ 3 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt create mode 100644 packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt new file mode 100644 index 0000000000000..a584894fed71e --- /dev/null +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt @@ -0,0 +1,72 @@ +/* + * 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 com.android.internal.systemui.lint + +import com.android.tools.lint.detector.api.Category +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.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiField +import org.jetbrains.uast.UReferenceExpression + +@Suppress("UnstableApiUsage") +class SoftwareBitmapDetector : Detector(), SourceCodeScanner { + + override fun getApplicableReferenceNames(): List { + return mutableListOf("ALPHA_8", "RGB_565", "ARGB_8888", "RGBA_F16", "RGBA_1010102") + } + + override fun visitReference( + context: JavaContext, + reference: UReferenceExpression, + referenced: PsiElement + ) { + + val evaluator = context.evaluator + if (evaluator.isMemberInClass(referenced as? PsiField, "android.graphics.Bitmap.Config")) { + context.report( + ISSUE, + referenced, + context.getNameLocation(referenced), + "Usage of Config.HARDWARE is highly encouraged." + ) + } + } + + companion object { + @JvmField + val ISSUE: Issue = + Issue.create( + id = "SoftwareBitmapDetector", + briefDescription = "Software bitmap detected. Please use Config.HARDWARE instead.", + explanation = + "Software bitmaps occupy twice as much memory, when compared to Config.HARDWARE. " + + "In case you need to manipulate the pixels, please consider to either use" + + "a shader (encouraged), or a short lived software bitmap.", + category = Category.PERFORMANCE, + priority = 8, + severity = Severity.WARNING, + implementation = Implementation(SoftwareBitmapDetector::class.java, + Scope.JAVA_FILE_SCOPE) + ) + } +} diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt index 78c6d7267dbab..c7c73d3c86a15 100644 --- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt @@ -27,10 +27,12 @@ import com.google.auto.service.AutoService class SystemUIIssueRegistry : IssueRegistry() { override val issues: List - get() = listOf(BindServiceViaContextDetector.ISSUE, + get() = listOf( + BindServiceViaContextDetector.ISSUE, BroadcastSentViaContextDetector.ISSUE, GetMainLooperViaContextDetector.ISSUE, - RegisterReceiverViaContextDetector.ISSUE + RegisterReceiverViaContextDetector.ISSUE, + SoftwareBitmapDetector.ISSUE, ) override val api: Int diff --git a/packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt new file mode 100644 index 0000000000000..890f2b8eb924c --- /dev/null +++ b/packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt @@ -0,0 +1,97 @@ +/* + * 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 com.android.internal.systemui.lint + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestFiles +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 + +@Suppress("UnstableApiUsage") +class SoftwareBitmapDetectorTest : LintDetectorTest() { + + override fun getDetector(): Detector = SoftwareBitmapDetector() + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + override fun getIssues(): List = listOf(SoftwareBitmapDetector.ISSUE) + + private val explanation = "Usage of Config.HARDWARE is highly encouraged." + + @Test + fun testSoftwareBitmap() { + lint().files( + TestFiles.java( + """ + import android.graphics.Bitmap; + + public class TestClass1 { + public void test() { + Bitmap.createBitmap(300, 300, Bitmap.Config.RGB_565); + Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); + } + } + """ + ).indented(), + *stubs) + .issues(SoftwareBitmapDetector.ISSUE) + .run() + .expectWarningCount(2) + .expectContains(explanation) + } + + @Test + fun testHardwareBitmap() { + lint().files( + TestFiles.java( + """ + import android.graphics.Bitmap; + + public class TestClass1 { + public void test() { + Bitmap.createBitmap(300, 300, Bitmap.Config.HARDWARE); + } + } + """ + ).indented(), + *stubs) + .issues(SoftwareBitmapDetector.ISSUE) + .run() + .expectWarningCount(0) + } + + private val bitmapStub: TestFile = java( + """ + package android.graphics; + + public class Bitmap { + public enum Config { + ARGB_8888, + RGB_565, + HARDWARE + } + public static Bitmap createBitmap(int width, int height, Config config) { + return null; + } + } + """ + ) + + private val stubs = arrayOf(bitmapStub) +}