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

Commit 10dcae69 authored by Peter Kalauskas's avatar Peter Kalauskas Committed by Selim Cinek
Browse files

Replace stubs with library references

Also, fix error where SoftwareBitmapDetector reported wrong location,
causing test failures due to "Incident (message, location) reported more
than once; this typically means that your detector is incorrectly
reaching the same element twice" on "line=-1"

Test: SystemUILintCheckerTest
Bug: 238923086
Change-Id: If60ebb0bb894710f46d9458d818be3c5b273bc35
parent 11c3d5db
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -40,6 +40,10 @@ java_test_host {
        "tests/**/*.kt",
        "tests/**/*.java",
    ],
    data: [
        ":framework",
        ":androidx.annotation_annotation",
    ],
    static_libs: [
        "SystemUILintChecker",
        "junit",
+3 −3
Original line number Diff line number Diff line
@@ -32,7 +32,8 @@ import org.jetbrains.uast.UReferenceExpression
class SoftwareBitmapDetector : Detector(), SourceCodeScanner {

    override fun getApplicableReferenceNames(): List<String> {
        return mutableListOf("ALPHA_8", "RGB_565", "ARGB_8888", "RGBA_F16", "RGBA_1010102")
        return mutableListOf(
            "ALPHA_8", "RGB_565", "ARGB_4444", "ARGB_8888", "RGBA_F16", "RGBA_1010102")
    }

    override fun visitReference(
@@ -40,13 +41,12 @@ class SoftwareBitmapDetector : Detector(), SourceCodeScanner {
            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),
                    context.getNameLocation(reference),
                    "Replace software bitmap with `Config.HARDWARE`"
            )
        }
+4 −210
Original line number Diff line number Diff line
@@ -18,185 +18,22 @@ package com.android.internal.systemui.lint

import com.android.annotations.NonNull
import com.android.tools.lint.checks.infrastructure.LintDetectorTest.java
import com.android.tools.lint.checks.infrastructure.TestFiles.LibraryReferenceTestFile
import java.io.File
import org.intellij.lang.annotations.Language

@Suppress("UnstableApiUsage")
@NonNull
private fun indentedJava(@NonNull @Language("JAVA") source: String) = java(source).indented()

internal val commonSettingsCode =
    """
public static float getFloat(ContentResolver cr, String name) { return 0.0f; }
public static long getLong(ContentResolver cr, String name) {
    return 0L;
}
public static int getInt(ContentResolver cr, String name) {
    return 0;
}
public static String getString(ContentResolver cr, String name) {
    return "";
}
public static float getFloat(ContentResolver cr, String name, float def) {
    return 0.0f;
}
public static long getLong(ContentResolver cr, String name, long def) {
    return 0L;
}
public static int getInt(ContentResolver cr, String name, int def) {
    return 0;
}
public static String getString(ContentResolver cr, String name, String def) {
    return "";
}
public static boolean putFloat(ContentResolver cr, String name, float value) {
    return true;
}
public static boolean putLong(ContentResolver cr, String name, long value) {
    return true;
}
public static boolean putInt(ContentResolver cr, String name, int value) {
    return true;
}
public static boolean putFloat(ContentResolver cr, String name) {
    return true;
}
public static boolean putString(ContentResolver cr, String name, String value) {
    return true;
}
"""

/*
 * This file contains stubs of framework APIs and System UI classes for testing purposes only. The
 * stubs are not used in the lint detectors themselves.
 */
internal val androidStubs =
    arrayOf(
        indentedJava(
            """
package android.app;

public class ActivityManager {
    public static int getCurrentUser() {}
}
"""
        ),
        indentedJava(
            """
package android.accounts;

public class AccountManager {
    public static AccountManager get(Context context) { return null; }
}
"""
        ),
        indentedJava(
            """
package android.os;
import android.content.pm.UserInfo;
import android.annotation.UserIdInt;

public class UserManager {
    public UserInfo getUserInfo(@UserIdInt int userId) {}
}
"""
        ),
        indentedJava("""
package android.annotation;

public @interface UserIdInt {}
"""),
        indentedJava("""
package android.content.pm;

public class UserInfo {}
"""),
        indentedJava("""
package android.os;

public class Looper {}
"""),
        indentedJava("""
package android.os;

public class Handler {}
"""),
        indentedJava("""
package android.content;

public class ServiceConnection {}
"""),
        indentedJava("""
package android.os;

public enum UserHandle {
    ALL
}
"""),
        indentedJava(
            """
package android.content;
import android.os.UserHandle;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;

public class Context {
    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {}
    public void registerReceiverAsUser(
            BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {}
    public void registerReceiverForAllUsers(
            BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission,
            Handler scheduler) {}
    public void sendBroadcast(Intent intent) {}
    public void sendBroadcast(Intent intent, String receiverPermission) {}
    public void sendBroadcastAsUser(Intent intent, UserHandle userHandle, String permission) {}
    public void bindService(Intent intent) {}
    public void bindServiceAsUser(
            Intent intent, ServiceConnection connection, int flags, UserHandle userHandle) {}
    public void unbindService(ServiceConnection connection) {}
    public Looper getMainLooper() { return null; }
    public Executor getMainExecutor() { return null; }
    public Handler getMainThreadHandler() { return null; }
    public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { return null; }
    public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);
}
"""
        ),
        indentedJava(
            """
package android.app;
import android.content.Context;

public class Activity extends Context {}
"""
        ),
        indentedJava(
            """
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;
    }
}
"""
        ),
        indentedJava("""
package android.content;

public class BroadcastReceiver {}
"""),
        indentedJava("""
package android.content;

public class IntentFilter {}
"""),
        LibraryReferenceTestFile(File("framework.jar").canonicalFile),
        LibraryReferenceTestFile(File("androidx.annotation_annotation.jar").canonicalFile),
        indentedJava(
            """
package com.android.systemui.settings;
@@ -206,49 +43,6 @@ public interface UserTracker {
    int getUserId();
    UserInfo getUserInfo();
}
"""
        ),
        indentedJava(
            """
package androidx.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.SOURCE;

@Retention(SOURCE)
@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER})
public @interface WorkerThread {
}
"""
        ),
        indentedJava(
            """
package android.provider;

public class Settings {
    public static final class Global {
        public static final String UNLOCK_SOUND = "unlock_sound";
        """ +
                commonSettingsCode +
                """
    }
    public static final class Secure {
    """ +
                commonSettingsCode +
                """
    }
    public static final class System {
    """ +
                commonSettingsCode +
                """
    }
}
"""
        ),
    )
+8 −9
Original line number Diff line number Diff line
@@ -51,12 +51,12 @@ class SoftwareBitmapDetectorTest : SystemUILintDetectorTest() {
            .run()
            .expect(
                """
                src/android/graphics/Bitmap.java:5: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap]
                        ARGB_8888,
                        ~~~~~~~~~
                src/android/graphics/Bitmap.java:6: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap]
                        RGB_565,
                src/TestClass.java:5: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap]
                      Bitmap.createBitmap(300, 300, Bitmap.Config.RGB_565);
                                                                  ~~~~~~~
                src/TestClass.java:6: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap]
                      Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
                                                                  ~~~~~~~~~
                0 errors, 2 warnings
                """
            )
@@ -76,8 +76,7 @@ class SoftwareBitmapDetectorTest : SystemUILintDetectorTest() {
                        }
                    }
                """
                    )
                    .indented(),
                ),
                *stubs
            )
            .issues(SoftwareBitmapDetector.ISSUE)
+33 −0
Original line number Diff line number Diff line
@@ -3,9 +3,42 @@ package com.android.internal.systemui.lint
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.checks.infrastructure.TestLintTask
import java.io.File
import org.junit.ClassRule
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.model.Statement

@Suppress("UnstableApiUsage")
@RunWith(JUnit4::class)
abstract class SystemUILintDetectorTest : LintDetectorTest() {

    companion object {
        @ClassRule
        @JvmField
        val libraryChecker: LibraryExists =
            LibraryExists("framework.jar", "androidx.annotation_annotation.jar")
    }

    class LibraryExists(vararg val libraryNames: String) : TestRule {
        override fun apply(base: Statement, description: Description): Statement {
            return object : Statement() {
                override fun evaluate() {
                    for (libName in libraryNames) {
                        val libFile = File(libName)
                        if (!libFile.canonicalFile.exists()) {
                            throw Exception(
                                "Could not find $libName in the test's working directory. " +
                                    "File ${libFile.absolutePath} does not exist."
                            )
                        }
                    }
                    base.evaluate()
                }
            }
        }
    }
    /**
     * Customize the lint task to disable SDK usage completely. This ensures that running the tests
     * in Android Studio has the same result as running the tests in atest