• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tools.layoutlib.create;
18 
19 import java.util.HashMap;
20 
21 /**
22  * Allows stub methods from LayoutLib to be overriden at runtime.
23  * <p/>
24  * Implementation note: all types required by this class(inner/outer classes & interfaces)
25  * must be referenced by the injectClass argument to {@link AsmGenerator} in Main.java;
26  * Otherwise they won't be accessible in layoutlib.jar at runtime.
27  */
28 public final class OverrideMethod {
29 
30     /** Map of method overridden. */
31     private static HashMap<String, MethodListener> sMethods = new HashMap<>();
32     /** Default listener for all method not listed in sMethods. Nothing if null. */
33     private static MethodListener sDefaultListener = null;
34 
35     /**
36      * Sets the default listener for all methods not specifically handled.
37      * Null means to do nothing.
38      */
39     @SuppressWarnings("UnusedDeclaration") // Used by Bridge by reflection for debug purposes.
setDefaultListener(MethodListener listener)40     public static void setDefaultListener(MethodListener listener) {
41         sDefaultListener = listener;
42     }
43 
44     /**
45      * Defines or reset a listener for the given method signature.
46      *
47      * @param signature The signature of the method being invoked, composed of the
48      *                  binary class name followed by the method descriptor (aka argument
49      *                  types). Example: "com/foo/MyClass/InnerClass/printInt(I)V"
50      * @param listener The new listener. Removes it if null.
51      */
setMethodListener(String signature, MethodListener listener)52     public static void setMethodListener(String signature, MethodListener listener) {
53         if (listener == null) {
54             sMethods.remove(signature);
55         } else {
56             sMethods.put(signature, listener);
57         }
58     }
59 
60     /**
61      * Invokes the specific listener for the given signature or the default one if defined.
62      * <p/>
63      * This version invokes the method listener for the void return type.
64      * <p/>
65      * Note: this is not intended to be used by the LayoutLib Bridge. It is intended to be called
66      * by the stubbed methods generated by the LayoutLib_create tool.
67      *
68      * @param signature The signature of the method being invoked, composed of the
69      *                  binary class name followed by the method descriptor (aka argument
70      *                  types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
71      * @param isNative True if the method was a native method.
72      * @param caller The calling object. Null for static methods, "this" for instance methods.
73      */
invokeV(String signature, boolean isNative, Object caller)74     public static void invokeV(String signature, boolean isNative, Object caller) {
75         MethodListener i = sMethods.get(signature);
76         if (i != null) {
77             i.onInvokeV(signature, isNative, caller);
78         } else if (sDefaultListener != null) {
79             sDefaultListener.onInvokeV(signature, isNative, caller);
80         }
81     }
82 
83     /**
84      * Invokes the specific listener for the int return type.
85      * @see #invokeV(String, boolean, Object)
86      */
invokeI(String signature, boolean isNative, Object caller)87     public static int invokeI(String signature, boolean isNative, Object caller) {
88         MethodListener i = sMethods.get(signature);
89         if (i != null) {
90             return i.onInvokeI(signature, isNative, caller);
91         } else if (sDefaultListener != null) {
92             return sDefaultListener.onInvokeI(signature, isNative, caller);
93         }
94         return 0;
95     }
96 
97     /**
98      * Invokes the specific listener for the long return type.
99      * @see #invokeV(String, boolean, Object)
100      */
invokeL(String signature, boolean isNative, Object caller)101     public static long invokeL(String signature, boolean isNative, Object caller) {
102         MethodListener i = sMethods.get(signature);
103         if (i != null) {
104             return i.onInvokeL(signature, isNative, caller);
105         } else if (sDefaultListener != null) {
106             return sDefaultListener.onInvokeL(signature, isNative, caller);
107         }
108         return 0;
109     }
110 
111     /**
112      * Invokes the specific listener for the float return type.
113      * @see #invokeV(String, boolean, Object)
114      */
invokeF(String signature, boolean isNative, Object caller)115     public static float invokeF(String signature, boolean isNative, Object caller) {
116         MethodListener i = sMethods.get(signature);
117         if (i != null) {
118             return i.onInvokeF(signature, isNative, caller);
119         } else if (sDefaultListener != null) {
120             return sDefaultListener.onInvokeF(signature, isNative, caller);
121         }
122         return 0;
123     }
124 
125     /**
126      * Invokes the specific listener for the double return type.
127      * @see #invokeV(String, boolean, Object)
128      */
invokeD(String signature, boolean isNative, Object caller)129     public static double invokeD(String signature, boolean isNative, Object caller) {
130         MethodListener i = sMethods.get(signature);
131         if (i != null) {
132             return i.onInvokeD(signature, isNative, caller);
133         } else if (sDefaultListener != null) {
134             return sDefaultListener.onInvokeD(signature, isNative, caller);
135         }
136         return 0;
137     }
138 
139     /**
140      * Invokes the specific listener for the object return type.
141      * @see #invokeV(String, boolean, Object)
142      */
invokeA(String signature, boolean isNative, Object caller)143     public static Object invokeA(String signature, boolean isNative, Object caller) {
144         MethodListener i = sMethods.get(signature);
145         if (i != null) {
146             return i.onInvokeA(signature, isNative, caller);
147         } else if (sDefaultListener != null) {
148             return sDefaultListener.onInvokeA(signature, isNative, caller);
149         }
150         return null;
151     }
152 }
153