diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 29b4708328781..75e1f3251cea1 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -46,6 +46,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView.OnItemClickListener; +import libcore.util.Objects; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -137,9 +138,9 @@ public class RemoteViews implements Parcelable, Filter { private static final OnClickHandler DEFAULT_ON_CLICK_HANDLER = new OnClickHandler(); - private static final Object sMethodsLock = new Object[0]; - private static final ArrayMap, ArrayMap> sMethods = - new ArrayMap, ArrayMap>(); + private static final Object[] sMethodsLock = new Object[0]; + private static final ArrayMap, ArrayMap>, Method>> sMethods = + new ArrayMap, ArrayMap>, Method>>(); private static final ThreadLocal sInvokeArgsTls = new ThreadLocal() { @Override protected Object[] initialValue() { @@ -147,6 +148,39 @@ public class RemoteViews implements Parcelable, Filter { } }; + /** + * Handle with care! + */ + static class MutablePair { + F first; + S second; + + MutablePair(F first, S second) { + this.first = first; + this.second = second; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof MutablePair)) { + return false; + } + MutablePair p = (MutablePair) o; + return Objects.equal(p.first, first) && Objects.equal(p.second, second); + } + + @Override + public int hashCode() { + return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode()); + } + } + + /** + * This pair is used to perform lookups in sMethods without causing allocations. + */ + private final MutablePair> mPair = + new MutablePair>(null, null); + /** * This annotation indicates that a subclass of View is alllowed to be used * with the {@link RemoteViews} mechanism. @@ -712,18 +746,21 @@ public class RemoteViews implements Parcelable, Filter { return rect; } - private static Method getMethod(View view, String methodName, Class paramType) { + private Method getMethod(View view, String methodName, Class paramType) { Method method; Class klass = view.getClass(); synchronized (sMethodsLock) { - ArrayMap methods = sMethods.get(klass); + ArrayMap>, Method> methods = sMethods.get(klass); if (methods == null) { - methods = new ArrayMap(); + methods = new ArrayMap>, Method>(); sMethods.put(klass, methods); } - method = methods.get(methodName); + mPair.first = methodName; + mPair.second = paramType; + + method = methods.get(mPair); if (method == null) { try { method = klass.getMethod(methodName, paramType); @@ -738,7 +775,7 @@ public class RemoteViews implements Parcelable, Filter { + methodName + getParameters(paramType)); } - methods.put(methodName, method); + methods.put(new MutablePair>(methodName, paramType), method); } } @@ -849,8 +886,8 @@ public class RemoteViews implements Parcelable, Filter { public final static int TAG = 3; } - private class ReflectionActionWithoutParams extends Action { - String methodName; + private final class ReflectionActionWithoutParams extends Action { + final String methodName; public final static int TAG = 5; @@ -1011,7 +1048,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Base class for the reflection actions. */ - private class ReflectionAction extends Action { + private final class ReflectionAction extends Action { static final int TAG = 2; static final int BOOLEAN = 1;