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

Commit 3423014c authored by Andrei-Valentin Onea's avatar Andrei-Valentin Onea Committed by Gerrit Code Review
Browse files

Merge "Support all UnsupportedAppUsage annotations in processor"

parents 52cd14f1 5e226140
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -763,6 +763,7 @@ java_library_host {
    srcs: [
        "core/java/android/annotation/IntDef.java",
        "core/java/android/annotation/UnsupportedAppUsage.java",
        ":unsupportedappusage_annotation_files",
    ],
}

+39 −15
Original line number Diff line number Diff line
@@ -20,12 +20,13 @@ import static javax.lang.model.element.ElementKind.PACKAGE;
import static javax.tools.Diagnostic.Kind.ERROR;
import static javax.tools.Diagnostic.Kind.WARNING;

import android.annotation.UnsupportedAppUsage;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.sun.tools.javac.code.Type;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -69,6 +70,7 @@ public class SignatureBuilder {
        public SignatureBuilderException(String message) {
            super(message);
        }

        public void report(Element offendingElement) {
            mMessager.printMessage(ERROR, getMessage(), offendingElement);
        }
@@ -191,8 +193,13 @@ public class SignatureBuilder {
        return sig.toString();
    }

    public String buildSignature(Element element) {
        UnsupportedAppUsage uba = element.getAnnotation(UnsupportedAppUsage.class);
    /**
     * Creates the signature for an annotated element.
     *
     * @param annotationType type of annotation being processed.
     * @param element        element for which we want to create a signature.
     */
    public String buildSignature(Class<? extends Annotation> annotationType, Element element) {
        try {
            String signature;
            switch (element.getKind()) {
@@ -208,18 +215,35 @@ public class SignatureBuilder {
                default:
                    return null;
            }
            // if we have an expected signature on the annotation, warn if it doesn't match.
            if (!Strings.isNullOrEmpty(uba.expectedSignature())) {
                if (!signature.equals(uba.expectedSignature())) {
            // Obtain annotation objects
            Annotation annotation = element.getAnnotation(annotationType);
            if (annotation == null) {
                throw new IllegalStateException(
                        "Element doesn't have any UnsupportedAppUsage annotation");
            }
            try {
                Method expectedSignatureMethod = annotationType.getMethod("expectedSignature");
                // If we have an expected signature on the annotation, warn if it doesn't match.
                String expectedSignature = expectedSignatureMethod.invoke(annotation).toString();
                if (!Strings.isNullOrEmpty(expectedSignature)) {
                    if (!signature.equals(expectedSignature)) {
                        mMessager.printMessage(
                                WARNING,
                            String.format("Expected signature doesn't match generated signature.\n"
                                String.format(
                                        "Expected signature doesn't match generated signature.\n"
                                                + " Expected:  %s\n Generated: %s",
                                    uba.expectedSignature(), signature),
                                        expectedSignature, signature),
                                element);
                    }
                }
                return signature;
            } catch (NoSuchMethodException e) {
                throw new IllegalStateException(
                        "Annotation type does not have expectedSignature parameter", e);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new IllegalStateException(
                        "Could not get expectedSignature parameter for annotation", e);
            }
        } catch (SignatureBuilderException problem) {
            problem.report(element);
            return null;
+42 −30
Original line number Diff line number Diff line
@@ -18,9 +18,8 @@ package android.processor.unsupportedappusage;

import static javax.tools.StandardLocation.CLASS_OUTPUT;

import android.annotation.UnsupportedAppUsage;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Pair;
@@ -28,6 +27,7 @@ import com.sun.tools.javac.util.Position;

import java.io.IOException;
import java.io.PrintStream;
import java.lang.annotation.Annotation;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
@@ -47,14 +47,14 @@ import javax.lang.model.element.TypeElement;
/**
 * Annotation processor for {@link UnsupportedAppUsage} annotations.
 *
 * This processor currently outputs two things:
 * 1. A greylist.txt containing dex signatures of all annotated elements.
 * 2. A CSV file with a mapping of dex signatures to corresponding source positions.
 * This processor currently outputs a CSV file with a mapping of dex signatures to corresponding
 * source positions.
 *
 * The first will be used at a later stage of the build to add access flags to the dex file. The
 * second is used for automating updates to the annotations themselves.
 * This is used for automating updates to the annotations themselves.
 */
@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage"})
@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage",
        "dalvik.annotation.compat.UnsupportedAppUsage"
})
public class UnsupportedAppUsageProcessor extends AbstractProcessor {

    // Package name for writing output. Output will be written to the "class output" location within
@@ -62,6 +62,13 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor {
    private static final String PACKAGE = "unsupportedappusage";
    private static final String INDEX_CSV = "unsupportedappusage_index.csv";

    private static final ImmutableSet<Class<? extends Annotation>> SUPPORTED_ANNOTATIONS =
            ImmutableSet.of(android.annotation.UnsupportedAppUsage.class,
                    dalvik.annotation.compat.UnsupportedAppUsage.class);
    private static final ImmutableSet<String> SUPPORTED_ANNOTATION_NAMES =
            SUPPORTED_ANNOTATIONS.stream().map(annotation -> annotation.getCanonicalName()).collect(
                    ImmutableSet.toImmutableSet());

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
@@ -92,8 +99,7 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor {
    private AnnotationMirror getUnsupportedAppUsageAnnotationMirror(Element e) {
        for (AnnotationMirror m : e.getAnnotationMirrors()) {
            TypeElement type = (TypeElement) m.getAnnotationType().asElement();
            if (type.getQualifiedName().toString().equals(
                    UnsupportedAppUsage.class.getCanonicalName())) {
            if (SUPPORTED_ANNOTATION_NAMES.contains(type.getQualifiedName().toString())) {
                return m;
            }
        }
@@ -164,20 +170,25 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor {
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Map<String, Element> signatureMap = new TreeMap<>();
        SignatureBuilder sb = new SignatureBuilder(processingEnv.getMessager());
        for (Class<? extends Annotation> supportedAnnotation : SUPPORTED_ANNOTATIONS) {
            Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith(
                UnsupportedAppUsage.class);
                    supportedAnnotation);
            if (annotated.size() == 0) {
            return true;
                continue;
            }
        // build signatures for each annotated member, and put them in a map of signature to member
        Map<String, Element> signatureMap = new TreeMap<>();
        SignatureBuilder sb = new SignatureBuilder(processingEnv.getMessager());
            // Build signatures for each annotated member and put them in a map from signature to
            // member.
            for (Element e : annotated) {
            String sig = sb.buildSignature(e);
                String sig = sb.buildSignature(supportedAnnotation, e);
                if (sig != null) {
                    signatureMap.put(sig, e);
                }
            }
        }

        if (!signatureMap.isEmpty()) {
            try {
                writeToFile(INDEX_CSV,
                        getCsvHeaders(),
@@ -187,6 +198,7 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor {
            } catch (IOException e) {
                throw new RuntimeException("Failed to write output", e);
            }
        }
        return true;
    }
}