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

Commit 650d7804 authored by Diego Perez's avatar Diego Perez Committed by Android (Google) Code Review
Browse files

Merge "Add ability to promote classes to public visibility"

parents ff5659fb b74f7485
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.stream.Collectors;

/**
 * Class that generates a new JAR from a list of classes, some of which are to be kept as-is
@@ -78,6 +79,8 @@ public class AsmGenerator {
    private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap;
    /** A map { FQCN => set { field names } } which should be promoted to public visibility */
    private final Map<String, Set<String>> mPromotedFields;
    /** A list of classes to be promoted to public visibility */
    private final Set<String> mPromotedClasses;

    /**
     * Creates a new generator that can generate the output JAR with the stubbed classes.
@@ -179,6 +182,9 @@ public class AsmGenerator {
        addToMap(createInfo.getPromotedFields(), mPromotedFields);

        mInjectedMethodsMap = createInfo.getInjectedMethodsMap();

        mPromotedClasses =
                Arrays.stream(createInfo.getPromotedClasses()).collect(Collectors.toSet());
    }

    /**
@@ -400,7 +406,11 @@ public class AsmGenerator {
        if (promoteFields != null && !promoteFields.isEmpty()) {
            cv = new PromoteFieldClassAdapter(cv, promoteFields);
        }
        if (!mPromotedClasses.isEmpty()) {
            cv = new PromoteClassClassAdapter(cv, mPromotedClasses);
        }
        cr.accept(cv, 0);

        return cw.toByteArray();
    }

+12 −0
Original line number Diff line number Diff line
@@ -112,6 +112,11 @@ public final class CreateInfo implements ICreateInfo {
        return PROMOTED_FIELDS;
    }

    @Override
    public String[] getPromotedClasses() {
        return PROMOTED_CLASSES;
    }

    @Override
    public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
        return INJECTED_METHODS;
@@ -343,6 +348,13 @@ public final class CreateInfo implements ICreateInfo {
        "android.graphics.FontFamily#mBuilderPtr"
    };

    /**
     * List of classes to be promoted to public visibility. Prefer using PROMOTED_FIELDS to this
     * if possible.
     */
    private final static String[] PROMOTED_CLASSES = new String[] {
    };

    /**
     * List of classes for which the methods returning them should be deleted.
     * The array contains a list of null terminated section starting with the name of the class
+5 −0
Original line number Diff line number Diff line
@@ -77,6 +77,11 @@ public interface ICreateInfo {
     */
    String[] getPromotedFields();

    /**
     * Returns a list of classes to be promoted to public visibility.
     */
    String[] getPromotedClasses();

    /**
     * Returns a map from binary FQCN className to {@link InjectMethodRunnable} which will be
     * called to inject methods into a class.
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.tools.layoutlib.create;

import org.objectweb.asm.ClassVisitor;

import java.util.Set;
import java.util.stream.Collectors;

import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;

/**
 * Promotes given classes to public visibility.
 */
public class PromoteClassClassAdapter extends ClassVisitor {

    private final Set<String> mClassNames;
    private static final int CLEAR_PRIVATE_MASK = ~(ACC_PRIVATE | ACC_PROTECTED);

    public PromoteClassClassAdapter(ClassVisitor cv, Set<String> classNames) {
        super(Main.ASM_VERSION, cv);
        mClassNames =
                classNames.stream().map(name -> name.replace(".", "/")).collect(Collectors.toSet());
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName,
            String[] interfaces) {
        if (mClassNames.contains(name)) {
            if ((access & ACC_PUBLIC) == 0) {
                access = (access & CLEAR_PRIVATE_MASK) | ACC_PUBLIC;
            }
        }

        super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
        if (mClassNames.contains(name)) {
            if ((access & ACC_PUBLIC) == 0) {
                access = (access & CLEAR_PRIVATE_MASK) | ACC_PUBLIC;
            }
        }

        super.visitInnerClass(name, outerName, innerName, access);
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
public class PromoteFieldClassAdapter extends ClassVisitor {

    private final Set<String> mFieldNames;
    private static final int ACC_NOT_PUBLIC = ~(ACC_PRIVATE | ACC_PROTECTED);
    private static final int CLEAR_PRIVATE_MASK = ~(ACC_PRIVATE | ACC_PROTECTED);

    public PromoteFieldClassAdapter(ClassVisitor cv, Set<String> fieldNames) {
        super(Main.ASM_VERSION, cv);
@@ -43,7 +43,7 @@ public class PromoteFieldClassAdapter extends ClassVisitor {
            Object value) {
        if (mFieldNames.contains(name)) {
            if ((access & ACC_PUBLIC) == 0) {
                access = (access & ACC_NOT_PUBLIC) | ACC_PUBLIC;
                access = (access & CLEAR_PRIVATE_MASK) | ACC_PUBLIC;
            }
        }
        return super.visitField(access, name, desc, signature, value);
Loading