Loading tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import com.android.tools.layoutlib.java.AutoCloseable; import com.android.tools.layoutlib.java.Charsets; import com.android.tools.layoutlib.java.IntegralToString; import com.android.tools.layoutlib.java.LinkedHashMap_Delegate; import com.android.tools.layoutlib.java.Objects; import com.android.tools.layoutlib.java.System_Delegate; import com.android.tools.layoutlib.java.UnsafeByteSequence; Loading Loading @@ -133,6 +134,7 @@ public final class CreateInfo implements ICreateInfo { UnsafeByteSequence.class, Charsets.class, System_Delegate.class, LinkedHashMap_Delegate.class, }; /** Loading tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java +30 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.tools.layoutlib.create; import com.android.tools.layoutlib.java.LinkedHashMap_Delegate; import com.android.tools.layoutlib.java.System_Delegate; import org.objectweb.asm.ClassVisitor; Loading @@ -26,8 +27,10 @@ import org.objectweb.asm.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; /** Loading @@ -44,7 +47,7 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor { "([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V", "([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V")); private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(2); private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(5); private static final String ANDROID_LOCALE_CLASS = "com/android/layoutlib/bridge/android/AndroidLocale"; Loading Loading @@ -74,7 +77,8 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor { // Case 2: java.util.Locale.toLanguageTag() and java.util.Locale.getScript() METHOD_REPLACERS.add(new MethodReplacer() { String LOCALE_TO_STRING = Type.getMethodDescriptor(STRING, Type.getType(Locale.class)); private final String LOCALE_TO_STRING = Type.getMethodDescriptor(STRING, Type.getType(Locale.class)); @Override public boolean isNeeded(String owner, String name, String desc) { Loading Loading @@ -129,6 +133,30 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor { mi.owner = Type.getInternalName(System_Delegate.class); } }); // Case 5: java.util.LinkedHashMap.eldest() METHOD_REPLACERS.add(new MethodReplacer() { private final String VOID_TO_MAP_ENTRY = Type.getMethodDescriptor(Type.getType(Map.Entry.class)); private final String LINKED_HASH_MAP = Type.getInternalName(LinkedHashMap.class); @Override public boolean isNeeded(String owner, String name, String desc) { return LINKED_HASH_MAP.equals(owner) && "eldest".equals(name) && VOID_TO_MAP_ENTRY.equals(desc); } @Override public void replace(MethodInformation mi) { assert isNeeded(mi.owner, mi.name, mi.desc); mi.opcode = Opcodes.INVOKESTATIC; mi.owner = Type.getInternalName(LinkedHashMap_Delegate.class); mi.desc = Type.getMethodDescriptor( Type.getType(Map.Entry.class), Type.getType(LinkedHashMap.class)); } }); } public static boolean isReplacementNeeded(String owner, String name, String desc) { Loading tools/layoutlib/create/src/com/android/tools/layoutlib/java/LinkedHashMap_Delegate.java 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.java; import com.android.tools.layoutlib.create.ReplaceMethodCallsAdapter; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; /** * Provides alternate implementation to java.util.LinkedHashMap#eldest(), which is present as a * non-public method in the Android VM, but not present on the host VM. This is injected in the * layoutlib using {@link ReplaceMethodCallsAdapter}. */ public class LinkedHashMap_Delegate { public static <K,V> Map.Entry<K,V> eldest(LinkedHashMap<K,V> map) { Iterator<Entry<K, V>> iterator = map.entrySet().iterator(); return iterator.hasNext() ? iterator.next() : null; } } Loading
tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import com.android.tools.layoutlib.java.AutoCloseable; import com.android.tools.layoutlib.java.Charsets; import com.android.tools.layoutlib.java.IntegralToString; import com.android.tools.layoutlib.java.LinkedHashMap_Delegate; import com.android.tools.layoutlib.java.Objects; import com.android.tools.layoutlib.java.System_Delegate; import com.android.tools.layoutlib.java.UnsafeByteSequence; Loading Loading @@ -133,6 +134,7 @@ public final class CreateInfo implements ICreateInfo { UnsafeByteSequence.class, Charsets.class, System_Delegate.class, LinkedHashMap_Delegate.class, }; /** Loading
tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java +30 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.tools.layoutlib.create; import com.android.tools.layoutlib.java.LinkedHashMap_Delegate; import com.android.tools.layoutlib.java.System_Delegate; import org.objectweb.asm.ClassVisitor; Loading @@ -26,8 +27,10 @@ import org.objectweb.asm.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; /** Loading @@ -44,7 +47,7 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor { "([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V", "([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V")); private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(2); private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(5); private static final String ANDROID_LOCALE_CLASS = "com/android/layoutlib/bridge/android/AndroidLocale"; Loading Loading @@ -74,7 +77,8 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor { // Case 2: java.util.Locale.toLanguageTag() and java.util.Locale.getScript() METHOD_REPLACERS.add(new MethodReplacer() { String LOCALE_TO_STRING = Type.getMethodDescriptor(STRING, Type.getType(Locale.class)); private final String LOCALE_TO_STRING = Type.getMethodDescriptor(STRING, Type.getType(Locale.class)); @Override public boolean isNeeded(String owner, String name, String desc) { Loading Loading @@ -129,6 +133,30 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor { mi.owner = Type.getInternalName(System_Delegate.class); } }); // Case 5: java.util.LinkedHashMap.eldest() METHOD_REPLACERS.add(new MethodReplacer() { private final String VOID_TO_MAP_ENTRY = Type.getMethodDescriptor(Type.getType(Map.Entry.class)); private final String LINKED_HASH_MAP = Type.getInternalName(LinkedHashMap.class); @Override public boolean isNeeded(String owner, String name, String desc) { return LINKED_HASH_MAP.equals(owner) && "eldest".equals(name) && VOID_TO_MAP_ENTRY.equals(desc); } @Override public void replace(MethodInformation mi) { assert isNeeded(mi.owner, mi.name, mi.desc); mi.opcode = Opcodes.INVOKESTATIC; mi.owner = Type.getInternalName(LinkedHashMap_Delegate.class); mi.desc = Type.getMethodDescriptor( Type.getType(Map.Entry.class), Type.getType(LinkedHashMap.class)); } }); } public static boolean isReplacementNeeded(String owner, String name, String desc) { Loading
tools/layoutlib/create/src/com/android/tools/layoutlib/java/LinkedHashMap_Delegate.java 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.java; import com.android.tools.layoutlib.create.ReplaceMethodCallsAdapter; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; /** * Provides alternate implementation to java.util.LinkedHashMap#eldest(), which is present as a * non-public method in the Android VM, but not present on the host VM. This is injected in the * layoutlib using {@link ReplaceMethodCallsAdapter}. */ public class LinkedHashMap_Delegate { public static <K,V> Map.Entry<K,V> eldest(LinkedHashMap<K,V> map) { Iterator<Entry<K, V>> iterator = map.entrySet().iterator(); return iterator.hasNext() ? iterator.next() : null; } }