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 com.android.tools.layoutlib.annotations.LayoutlibDelegate;
20 import com.android.tools.layoutlib.java.AutoCloseable;
21 import com.android.tools.layoutlib.java.Charsets;
22 import com.android.tools.layoutlib.java.IntegralToString;
23 import com.android.tools.layoutlib.java.LinkedHashMap_Delegate;
24 import com.android.tools.layoutlib.java.Objects;
25 import com.android.tools.layoutlib.java.System_Delegate;
26 import com.android.tools.layoutlib.java.UnsafeByteSequence;
27 
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Map;
32 import java.util.Set;
33 
34 /**
35  * Describes the work to be done by {@link AsmGenerator}.
36  */
37 public final class CreateInfo implements ICreateInfo {
38 
39     /**
40      * Returns the list of class from layoutlib_create to inject in layoutlib.
41      * The list can be empty but must not be null.
42      */
43     @Override
getInjectedClasses()44     public Class<?>[] getInjectedClasses() {
45         return INJECTED_CLASSES;
46     }
47 
48     /**
49      * Returns the list of methods to rewrite as delegates.
50      * The list can be empty but must not be null.
51      */
52     @Override
getDelegateMethods()53     public String[] getDelegateMethods() {
54         return DELEGATE_METHODS;
55     }
56 
57     /**
58      * Returns the list of classes on which to delegate all native methods.
59      * The list can be empty but must not be null.
60      */
61     @Override
getDelegateClassNatives()62     public String[] getDelegateClassNatives() {
63         return DELEGATE_CLASS_NATIVES;
64     }
65 
66     /**
67      * Returns The list of methods to stub out. Each entry must be in the form
68      * "package.package.OuterClass$InnerClass#MethodName".
69      * The list can be empty but must not be null.
70      * <p/>
71      * This usage is deprecated. Please use method 'delegates' instead.
72      */
73     @Override
getOverriddenMethods()74     public String[] getOverriddenMethods() {
75         return OVERRIDDEN_METHODS;
76     }
77 
78     /**
79      * Returns the list of classes to rename, must be an even list: the binary FQCN
80      * of class to replace followed by the new FQCN.
81      * The list can be empty but must not be null.
82      */
83     @Override
getRenamedClasses()84     public String[] getRenamedClasses() {
85         return RENAMED_CLASSES;
86     }
87 
88     /**
89      * Returns the list of classes for which the methods returning them should be deleted.
90      * The array contains a list of null terminated section starting with the name of the class
91      * to rename in which the methods are deleted, followed by a list of return types identifying
92      * the methods to delete.
93      * The list can be empty but must not be null.
94      */
95     @Override
getDeleteReturns()96     public String[] getDeleteReturns() {
97         return DELETE_RETURNS;
98     }
99 
100     /**
101      * Returns the list of classes to refactor, must be an even list: the binary FQCN of class to
102      * replace followed by the new FQCN. All references to the old class should be updated to the
103      * new class. The list can be empty but must not be null.
104      */
105     @Override
getJavaPkgClasses()106     public String[] getJavaPkgClasses() {
107       return JAVA_PKG_CLASSES;
108     }
109 
110     @Override
getExcludedClasses()111     public Set<String> getExcludedClasses() {
112         String[] refactoredClasses = getJavaPkgClasses();
113         int count = refactoredClasses.length / 2 + EXCLUDED_CLASSES.length;
114         Set<String> excludedClasses = new HashSet<>(count);
115         for (int i = 0; i < refactoredClasses.length; i+=2) {
116             excludedClasses.add(refactoredClasses[i]);
117         }
118         excludedClasses.addAll(Arrays.asList(EXCLUDED_CLASSES));
119         return excludedClasses;
120     }
121 
122     @Override
getPromotedFields()123     public String[] getPromotedFields() {
124         return PROMOTED_FIELDS;
125     }
126 
127     @Override
getInjectedMethodsMap()128     public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
129         return INJECTED_METHODS;
130     }
131 
132     //-----
133 
134     /**
135      * The list of class from layoutlib_create to inject in layoutlib.
136      */
137     private final static Class<?>[] INJECTED_CLASSES = new Class<?>[] {
138             OverrideMethod.class,
139             MethodListener.class,
140             MethodAdapter.class,
141             ICreateInfo.class,
142             CreateInfo.class,
143             LayoutlibDelegate.class,
144             InjectMethodRunnable.class,
145             InjectMethodRunnables.class,
146             /* Java package classes */
147             IntegralToString.class,
148             UnsafeByteSequence.class,
149             System_Delegate.class,
150             LinkedHashMap_Delegate.class,
151         };
152 
153     /**
154      * The list of methods to rewrite as delegates.
155      */
156     public final static String[] DELEGATE_METHODS = new String[] {
157         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
158         "android.content.res.Resources#getAnimation",
159         "android.content.res.Resources#getBoolean",
160         "android.content.res.Resources#getColor",
161         "android.content.res.Resources#getColorStateList",
162         "android.content.res.Resources#getDimension",
163         "android.content.res.Resources#getDimensionPixelOffset",
164         "android.content.res.Resources#getDimensionPixelSize",
165         "android.content.res.Resources#getDrawable",
166         "android.content.res.Resources#getIntArray",
167         "android.content.res.Resources#getInteger",
168         "android.content.res.Resources#getLayout",
169         "android.content.res.Resources#getResourceEntryName",
170         "android.content.res.Resources#getResourceName",
171         "android.content.res.Resources#getResourcePackageName",
172         "android.content.res.Resources#getResourceTypeName",
173         "android.content.res.Resources#getString",
174         "android.content.res.Resources#getStringArray",
175         "android.content.res.Resources#getText",
176         "android.content.res.Resources#getTextArray",
177         "android.content.res.Resources#getValue",
178         "android.content.res.Resources#getXml",
179         "android.content.res.Resources#loadXmlResourceParser",
180         "android.content.res.Resources#obtainAttributes",
181         "android.content.res.Resources#obtainTypedArray",
182         "android.content.res.Resources#openRawResource",
183         "android.content.res.Resources#openRawResourceFd",
184         "android.content.res.Resources$Theme#obtainStyledAttributes",
185         "android.content.res.Resources$Theme#resolveAttribute",
186         "android.content.res.Resources$Theme#resolveAttributes",
187         "android.content.res.AssetManager#newTheme",
188         "android.content.res.AssetManager#deleteTheme",
189         "android.content.res.TypedArray#getValueAt",
190         "android.content.res.TypedArray#obtain",
191         "android.graphics.BitmapFactory#finishDecode",
192         "android.graphics.BitmapFactory#setDensityFromOptions",
193         "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
194         "android.graphics.drawable.GradientDrawable#buildRing",
195         "android.graphics.FontFamily#addFont",
196         "android.graphics.Typeface#getSystemFontConfigLocation",
197         "android.graphics.Typeface#makeFamilyFromParsed",
198         "android.os.Handler#sendMessageAtTime",
199         "android.os.HandlerThread#run",
200         "android.preference.Preference#getView",
201         "android.text.format.DateFormat#is24HourFormat",
202         "android.text.Hyphenator#getSystemHyphenatorLocation",
203         "android.util.Xml#newPullParser",
204         "android.view.Choreographer#getInstance",
205         "android.view.Choreographer#getRefreshRate",
206         "android.view.Choreographer#scheduleVsyncLocked",
207         "android.view.Display#updateDisplayInfoLocked",
208         "android.view.Display#getWindowManager",
209         "android.view.HandlerActionQueue#postDelayed",
210         "android.view.LayoutInflater#rInflate",
211         "android.view.LayoutInflater#parseInclude",
212         "android.view.View#getWindowToken",
213         "android.view.View#isInEditMode",
214         "android.view.ViewRootImpl#isInTouchMode",
215         "android.view.WindowManagerGlobal#getWindowManagerService",
216         "android.view.inputmethod.InputMethodManager#getInstance",
217         "android.view.MenuInflater#registerMenu",
218         "android.view.RenderNode#getMatrix",
219         "android.view.RenderNode#nCreate",
220         "android.view.RenderNode#nDestroyRenderNode",
221         "android.view.RenderNode#nSetElevation",
222         "android.view.RenderNode#nGetElevation",
223         "android.view.RenderNode#nSetTranslationX",
224         "android.view.RenderNode#nGetTranslationX",
225         "android.view.RenderNode#nSetTranslationY",
226         "android.view.RenderNode#nGetTranslationY",
227         "android.view.RenderNode#nSetTranslationZ",
228         "android.view.RenderNode#nGetTranslationZ",
229         "android.view.RenderNode#nSetRotation",
230         "android.view.RenderNode#nGetRotation",
231         "android.view.RenderNode#nSetLeft",
232         "android.view.RenderNode#nSetTop",
233         "android.view.RenderNode#nSetRight",
234         "android.view.RenderNode#nSetBottom",
235         "android.view.RenderNode#nSetLeftTopRightBottom",
236         "android.view.RenderNode#nSetPivotX",
237         "android.view.RenderNode#nGetPivotX",
238         "android.view.RenderNode#nSetPivotY",
239         "android.view.RenderNode#nGetPivotY",
240         "android.view.RenderNode#nSetScaleX",
241         "android.view.RenderNode#nGetScaleX",
242         "android.view.RenderNode#nSetScaleY",
243         "android.view.RenderNode#nGetScaleY",
244         "android.view.RenderNode#nIsPivotExplicitlySet",
245         "android.view.ViewGroup#drawChild",
246         "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
247         "com.android.internal.util.XmlUtils#convertValueToInt",
248         "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
249         "dalvik.system.VMRuntime#newUnpaddedArray",
250         "libcore.io.MemoryMappedFile#mmapRO",
251         "libcore.io.MemoryMappedFile#close",
252         "libcore.io.MemoryMappedFile#bigEndianIterator",
253         "libcore.util.NativeAllocationRegistry#applyFreeFunction",
254     };
255 
256     /**
257      * The list of classes on which to delegate all native methods.
258      */
259     public final static String[] DELEGATE_CLASS_NATIVES = new String[] {
260         "android.animation.PropertyValuesHolder",
261         "android.graphics.Bitmap",
262         "android.graphics.BitmapFactory",
263         "android.graphics.BitmapShader",
264         "android.graphics.BlurMaskFilter",
265         "android.graphics.Canvas",
266         "android.graphics.ColorFilter",
267         "android.graphics.ColorMatrixColorFilter",
268         "android.graphics.ComposePathEffect",
269         "android.graphics.ComposeShader",
270         "android.graphics.CornerPathEffect",
271         "android.graphics.DashPathEffect",
272         "android.graphics.DiscretePathEffect",
273         "android.graphics.DrawFilter",
274         "android.graphics.EmbossMaskFilter",
275         "android.graphics.FontFamily",
276         "android.graphics.LayerRasterizer",
277         "android.graphics.LightingColorFilter",
278         "android.graphics.LinearGradient",
279         "android.graphics.MaskFilter",
280         "android.graphics.Matrix",
281         "android.graphics.NinePatch",
282         "android.graphics.Paint",
283         "android.graphics.PaintFlagsDrawFilter",
284         "android.graphics.Path",
285         "android.graphics.PathDashPathEffect",
286         "android.graphics.PathEffect",
287         "android.graphics.PathMeasure",
288         "android.graphics.PorterDuffColorFilter",
289         "android.graphics.PorterDuffXfermode",
290         "android.graphics.RadialGradient",
291         "android.graphics.Rasterizer",
292         "android.graphics.Region",
293         "android.graphics.Shader",
294         "android.graphics.SumPathEffect",
295         "android.graphics.SweepGradient",
296         "android.graphics.Typeface",
297         "android.graphics.Xfermode",
298         "android.graphics.drawable.AnimatedVectorDrawable",
299         "android.graphics.drawable.VectorDrawable",
300         "android.os.SystemClock",
301         "android.os.SystemProperties",
302         "android.text.AndroidBidi",
303         "android.text.StaticLayout",
304         "android.util.PathParser",
305         "android.view.Display",
306         "com.android.internal.util.VirtualRefBasePtr",
307         "com.android.internal.view.animation.NativeInterpolatorFactoryHelper",
308         "libcore.icu.ICU",
309     };
310 
311     /**
312      * The list of methods to stub out. Each entry must be in the form
313      *  "package.package.OuterClass$InnerClass#MethodName".
314      *  This usage is deprecated. Please use method 'delegates' instead.
315      */
316     private final static String[] OVERRIDDEN_METHODS = new String[] {
317     };
318 
319     /**
320      *  The list of classes to rename, must be an even list: the binary FQCN
321      *  of class to replace followed by the new FQCN.
322      */
323     private final static String[] RENAMED_CLASSES =
324         new String[] {
325             "android.os.ServiceManager",                       "android.os._Original_ServiceManager",
326             "android.util.LruCache",                           "android.util._Original_LruCache",
327             "android.view.SurfaceView",                        "android.view._Original_SurfaceView",
328             "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
329             "android.webkit.WebView",                          "android.webkit._Original_WebView",
330         };
331 
332     /**
333      * The list of class references to update, must be an even list: the binary
334      * FQCN of class to replace followed by the new FQCN. The classes to
335      * replace are to be excluded from the output.
336      */
337     private final static String[] JAVA_PKG_CLASSES =
338         new String[] {
339             "java.nio.charset.Charsets",                       "java.nio.charset.StandardCharsets",
340             "java.lang.IntegralToString",                      "com.android.tools.layoutlib.java.IntegralToString",
341             "java.lang.UnsafeByteSequence",                    "com.android.tools.layoutlib.java.UnsafeByteSequence",
342             // Use android.icu.text versions of DateFormat and SimpleDateFormat since the
343             // original ones do not match the Android implementation
344             "java.text.DateFormat",                            "android.icu.text.DateFormat",
345             "java.text.SimpleDateFormat",                      "android.icu.text.SimpleDateFormat",
346         };
347 
348     private final static String[] EXCLUDED_CLASSES =
349         new String[] {
350             "android.preference.PreferenceActivity",
351             "org.kxml2.io.KXmlParser"
352         };
353 
354     /**
355      * List of fields for which we will update the visibility to be public. This is sometimes
356      * needed when access from the delegate classes is needed.
357      */
358     private final static String[] PROMOTED_FIELDS = new String[] {
359         "android.graphics.drawable.VectorDrawable#mVectorState",
360         "android.view.Choreographer#mLastFrameTimeNanos"
361     };
362 
363     /**
364      * List of classes for which the methods returning them should be deleted.
365      * The array contains a list of null terminated section starting with the name of the class
366      * to rename in which the methods are deleted, followed by a list of return types identifying
367      * the methods to delete.
368      */
369     private final static String[] DELETE_RETURNS =
370         new String[] {
371             null };                         // separator, for next class/methods list.
372 
373     private final static Map<String, InjectMethodRunnable> INJECTED_METHODS =
374             new HashMap<String, InjectMethodRunnable>(1) {{
375                 put("android.content.Context",
376                         InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER);
377             }};
378 }
379