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

Commit e4598174 authored by Lucas Dupin's avatar Lucas Dupin
Browse files

Hardware bitmap linter

Encrouage engineers to use Config.HARDWARE instead of other types of
Bitmaps.

Test: atest SoftwareBitmapDetectorTest
Bug: 238923086
Change-Id: I3c2e789546c137d73b8a5ec5f7ef5755144b622d
parent 3bb0be43
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
/*
 * 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<String> {
        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)
            )
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -27,10 +27,12 @@ import com.google.auto.service.AutoService
class SystemUIIssueRegistry : IssueRegistry() {

    override val issues: List<Issue>
        get() = listOf(BindServiceViaContextDetector.ISSUE,
        get() = listOf(
                BindServiceViaContextDetector.ISSUE,
                BroadcastSentViaContextDetector.ISSUE,
                GetMainLooperViaContextDetector.ISSUE,
                RegisterReceiverViaContextDetector.ISSUE
                RegisterReceiverViaContextDetector.ISSUE,
                SoftwareBitmapDetector.ISSUE,
        )

    override val api: Int
+97 −0
Original line number Diff line number Diff line
/*
 * 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<Issue> = 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)
}