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.LinkedHashMap_Delegate;
21 import com.android.tools.layoutlib.java.System_Delegate;
22 
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Set;
28 
29 /**
30  * Describes the work to be done by {@link AsmGenerator}.
31  */
32 public final class CreateInfo implements ICreateInfo {
33 
34     @Override
getInjectedClasses()35     public Class<?>[] getInjectedClasses() {
36         return INJECTED_CLASSES;
37     }
38 
39     @Override
getDelegateMethods()40     public String[] getDelegateMethods() {
41         return DELEGATE_METHODS;
42     }
43 
44     @Override
getDelegateClassNatives()45     public String[] getDelegateClassNatives() {
46         return DELEGATE_CLASS_NATIVES;
47     }
48 
49     @Override
getRenamedClasses()50     public String[] getRenamedClasses() {
51         return RENAMED_CLASSES;
52     }
53 
54     @Override
getDeleteReturns()55     public String[] getDeleteReturns() {
56         return DELETE_RETURNS;
57     }
58 
59     @Override
getJavaPkgClasses()60     public String[] getJavaPkgClasses() {
61       return JAVA_PKG_CLASSES;
62     }
63 
64     @Override
getRefactoredClasses()65     public String[] getRefactoredClasses() {
66         return REFACTOR_CLASSES;
67     }
68 
69     @Override
getExcludedClasses()70     public String[] getExcludedClasses() {
71         String[] refactoredClasses = getJavaPkgClasses();
72         int count = refactoredClasses.length / 2 + EXCLUDED_CLASSES.length;
73         Set<String> excludedClasses = new HashSet<>(count);
74         for (int i = 0; i < refactoredClasses.length; i+=2) {
75             excludedClasses.add(refactoredClasses[i]);
76         }
77         excludedClasses.addAll(Arrays.asList(EXCLUDED_CLASSES));
78         return excludedClasses.toArray(new String[0]);
79     }
80 
81     @Override
getPromotedFields()82     public String[] getPromotedFields() {
83         return PROMOTED_FIELDS;
84     }
85 
86     @Override
getPromotedClasses()87     public String[] getPromotedClasses() {
88         return PROMOTED_CLASSES;
89     }
90 
91     @Override
getInjectedMethodsMap()92     public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
93         return INJECTED_METHODS;
94     }
95 
96     //-----
97 
98     /**
99      * The list of class from layoutlib_create to inject in layoutlib.
100      */
101     private final static Class<?>[] INJECTED_CLASSES = new Class<?>[] {
102             OverrideMethod.class,
103             MethodListener.class,
104             MethodAdapter.class,
105             ICreateInfo.class,
106             CreateInfo.class,
107             LayoutlibDelegate.class,
108             InjectMethodRunnable.class,
109             InjectMethodRunnables.class,
110             /* Java package classes */
111             System_Delegate.class,
112             LinkedHashMap_Delegate.class,
113         };
114 
115     /**
116      * The list of methods to rewrite as delegates.
117      */
118     public final static String[] DELEGATE_METHODS = new String[] {
119         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
120         "android.content.res.Resources#getAnimation",
121         "android.content.res.Resources#getAttributeSetSourceResId",
122         "android.content.res.Resources#getBoolean",
123         "android.content.res.Resources#getColor",
124         "android.content.res.Resources#getColorStateList",
125         "android.content.res.Resources#getDimension",
126         "android.content.res.Resources#getDimensionPixelOffset",
127         "android.content.res.Resources#getDimensionPixelSize",
128         "android.content.res.Resources#getDrawable",
129         "android.content.res.Resources#getFloat",
130         "android.content.res.Resources#getFont",
131         "android.content.res.Resources#getIdentifier",
132         "android.content.res.Resources#getIntArray",
133         "android.content.res.Resources#getInteger",
134         "android.content.res.Resources#getLayout",
135         "android.content.res.Resources#getQuantityString",
136         "android.content.res.Resources#getQuantityText",
137         "android.content.res.Resources#getResourceEntryName",
138         "android.content.res.Resources#getResourceName",
139         "android.content.res.Resources#getResourcePackageName",
140         "android.content.res.Resources#getResourceTypeName",
141         "android.content.res.Resources#getString",
142         "android.content.res.Resources#getStringArray",
143         "android.content.res.Resources#getText",
144         "android.content.res.Resources#getTextArray",
145         "android.content.res.Resources#getValue",
146         "android.content.res.Resources#getValueForDensity",
147         "android.content.res.Resources#getXml",
148         "android.content.res.Resources#loadXmlResourceParser",
149         "android.content.res.Resources#obtainAttributes",
150         "android.content.res.Resources#obtainTypedArray",
151         "android.content.res.Resources#openRawResource",
152         "android.content.res.Resources#openRawResourceFd",
153         "android.content.res.Resources$Theme#obtainStyledAttributes",
154         "android.content.res.Resources$Theme#resolveAttribute",
155         "android.content.res.Resources$Theme#resolveAttributes",
156         "android.content.res.AssetManager#nativeCreate",
157         "android.content.res.AssetManager#nativeDestroy",
158         "android.content.res.AssetManager#nativeThemeCreate",
159         "android.content.res.AssetManager#nativeThemeDestroy",
160         "android.content.res.AssetManager#getAssignedPackageIdentifiers",
161         "android.content.res.AssetManager#nativeCreateIdmapsForStaticOverlaysTargetingAndroid",
162         "android.content.res.TypedArray#getValueAt",
163         "android.content.res.TypedArray#obtain",
164         "android.graphics.BitmapFactory#finishDecode",
165         "android.graphics.BitmapFactory#setDensityFromOptions",
166         "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
167         "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#onDraw",
168         "android.graphics.drawable.GradientDrawable#buildRing",
169         "android.graphics.drawable.AdaptiveIconDrawable#<init>",
170         "android.graphics.drawable.DrawableInflater#inflateFromClass",
171         "android.graphics.FontFamily#addFont",
172         "android.graphics.Typeface#create",
173         "android.graphics.Typeface$Builder#createAssetUid",
174         "android.graphics.fonts.Font$Builder#createBuffer",
175         "android.graphics.fonts.SystemFonts#buildSystemFallback",
176         "android.os.Binder#getNativeBBinderHolder",
177         "android.os.Binder#getNativeFinalizer",
178         "android.os.Handler#sendMessageAtTime",
179         "android.os.HandlerThread#run",
180         "android.preference.Preference#getView",
181         "android.text.format.DateFormat#is24HourFormat",
182         "android.util.Xml#newPullParser",
183         "android.view.Choreographer#getInstance",
184         "android.view.Choreographer#getRefreshRate",
185         "android.view.Choreographer#scheduleVsyncLocked",
186         "android.view.Display#updateDisplayInfoLocked",
187         "android.view.Display#getWindowManager",
188         "android.view.HandlerActionQueue#postDelayed",
189         "android.view.LayoutInflater#initPrecompiledViews",
190         "android.view.LayoutInflater#rInflate",
191         "android.view.LayoutInflater#parseInclude",
192         "android.view.View#draw",
193         "android.view.View#dispatchDetachedFromWindow",
194         "android.view.View#layout",
195         "android.view.View#measure",
196         "android.view.View#getWindowToken",
197         "android.view.View#isInEditMode",
198         "android.view.ViewRootImpl#isInTouchMode",
199         "android.view.WindowManagerGlobal#getWindowManagerService",
200         "android.view.inputmethod.InputMethodManager#isInEditMode",
201         "android.view.MenuInflater#registerMenu",
202         "android.graphics.RenderNode#getMatrix",
203         "android.graphics.RenderNode#nCreate",
204         "android.graphics.RenderNode#nGetNativeFinalizer",
205         "android.graphics.RenderNode#nSetElevation",
206         "android.graphics.RenderNode#nGetElevation",
207         "android.graphics.RenderNode#nSetTranslationX",
208         "android.graphics.RenderNode#nGetTranslationX",
209         "android.graphics.RenderNode#nSetTranslationY",
210         "android.graphics.RenderNode#nGetTranslationY",
211         "android.graphics.RenderNode#nSetTranslationZ",
212         "android.graphics.RenderNode#nGetTranslationZ",
213         "android.graphics.RenderNode#nSetRotation",
214         "android.graphics.RenderNode#nGetRotation",
215         "android.graphics.RenderNode#nSetLeft",
216         "android.graphics.RenderNode#nSetTop",
217         "android.graphics.RenderNode#nSetRight",
218         "android.graphics.RenderNode#nSetBottom",
219         "android.graphics.RenderNode#nSetLeftTopRightBottom",
220         "android.graphics.RenderNode#nSetPivotX",
221         "android.graphics.RenderNode#nGetPivotX",
222         "android.graphics.RenderNode#nSetPivotY",
223         "android.graphics.RenderNode#nGetPivotY",
224         "android.graphics.RenderNode#nSetScaleX",
225         "android.graphics.RenderNode#nGetScaleX",
226         "android.graphics.RenderNode#nSetScaleY",
227         "android.graphics.RenderNode#nGetScaleY",
228         "android.graphics.RenderNode#nIsPivotExplicitlySet",
229         "android.provider.DeviceConfig#getBoolean",
230         "android.provider.DeviceConfig#getFloat",
231         "android.provider.DeviceConfig#getInt",
232         "android.provider.DeviceConfig#getLong",
233         "android.provider.DeviceConfig#getString",
234         "android.view.PointerIcon#loadResource",
235         "android.view.PointerIcon#registerDisplayListener",
236         "android.view.SurfaceControl#nativeCreateTransaction",
237         "android.view.SurfaceControl#nativeGetNativeTransactionFinalizer",
238         "android.view.ViewGroup#drawChild",
239         "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
240         "com.android.internal.util.XmlUtils#convertValueToInt",
241         "dalvik.system.VMRuntime#getNotifyNativeInterval",
242         "dalvik.system.VMRuntime#newUnpaddedArray",
243         "libcore.io.MemoryMappedFile#mmapRO",
244         "libcore.io.MemoryMappedFile#close",
245         "libcore.io.MemoryMappedFile#bigEndianIterator",
246         "libcore.util.NativeAllocationRegistry#applyFreeFunction",
247         "libcore.util.NativeAllocationRegistry#registerNativeAllocation",
248     };
249 
250     /**
251      * The list of classes on which to delegate all native methods.
252      */
253     public final static String[] DELEGATE_CLASS_NATIVES = new String[] {
254         "android.animation.PropertyValuesHolder",
255         "android.graphics.BaseCanvas",
256         "android.graphics.Bitmap",
257         "android.graphics.BitmapFactory",
258         "android.graphics.BitmapShader",
259         "android.graphics.BlendModeColorFilter",
260         "android.graphics.BlurMaskFilter",
261         "android.graphics.Canvas",
262         "android.graphics.Color",
263         "android.graphics.ColorFilter",
264         "android.graphics.ColorMatrixColorFilter",
265         "android.graphics.ColorSpace$Rgb",
266         "android.graphics.ComposePathEffect",
267         "android.graphics.ComposeShader",
268         "android.graphics.CornerPathEffect",
269         "android.graphics.DashPathEffect",
270         "android.graphics.DiscretePathEffect",
271         "android.graphics.DrawFilter",
272         "android.graphics.EmbossMaskFilter",
273         "android.graphics.FontFamily",
274         "android.graphics.LightingColorFilter",
275         "android.graphics.LinearGradient",
276         "android.graphics.MaskFilter",
277         "android.graphics.Matrix",
278         "android.graphics.NinePatch",
279         "android.graphics.Paint",
280         "android.graphics.PaintFlagsDrawFilter",
281         "android.graphics.Path",
282         "android.graphics.PathDashPathEffect",
283         "android.graphics.PathEffect",
284         "android.graphics.PathMeasure",
285         "android.graphics.PorterDuffColorFilter",
286         "android.graphics.RadialGradient",
287         "android.graphics.Region",
288         "android.graphics.Shader",
289         "android.graphics.SumPathEffect",
290         "android.graphics.SweepGradient",
291         "android.graphics.Typeface",
292         "android.graphics.animation.NativeInterpolatorFactory",
293         "android.graphics.drawable.AnimatedVectorDrawable",
294         "android.graphics.drawable.VectorDrawable",
295         "android.graphics.fonts.Font$Builder",
296         "android.graphics.fonts.FontFamily$Builder",
297         "android.graphics.text.MeasuredText",
298         "android.graphics.text.MeasuredText$Builder",
299         "android.graphics.text.LineBreaker",
300         "android.os.SystemClock",
301         "android.os.SystemProperties",
302         "android.util.PathParser",
303         "android.view.Display",
304         "com.android.internal.util.VirtualRefBasePtr",
305         "libcore.icu.ICU",
306     };
307 
308     /**
309      *  The list of classes to rename, must be an even list: the binary FQCN
310      *  of class to replace followed by the new FQCN.
311      */
312     private final static String[] RENAMED_CLASSES =
313         new String[] {
314             "android.os.ServiceManager",                       "android.os._Original_ServiceManager",
315             "android.view.textservice.TextServicesManager",    "android.view.textservice._Original_TextServicesManager",
316             "android.view.SurfaceView",                        "android.view._Original_SurfaceView",
317             "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
318             "android.view.accessibility.AccessibilityNodeIdManager", "android.view.accessibility._Original_AccessibilityNodeIdManager",
319             "android.webkit.WebView",                          "android.webkit._Original_WebView",
320             "android.graphics.ImageDecoder",                   "android.graphics._Original_ImageDecoder",
321         };
322 
323     /**
324      * The list of class references to update, must be an even list: the binary
325      * FQCN of class to replace followed by the new FQCN. The classes to
326      * replace are to be excluded from the output.
327      */
328     private final static String[] JAVA_PKG_CLASSES =
329         new String[] {
330                 "sun.misc.Cleaner",                                "com.android.layoutlib.bridge.libcore.util.Cleaner",
331         };
332 
333     /**
334      * List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
335      * {@link #getJavaPkgClasses()}.
336      * Classes included here will be renamed and then all their references in any other classes
337      * will be also modified.
338      * FQCN of class to refactor followed by its new FQCN.
339      */
340     private final static String[] REFACTOR_CLASSES =
341             new String[] {
342                     "android.os.Build",                                "android.os._Original_Build",
343             };
344 
345     private final static String[] EXCLUDED_CLASSES =
346         new String[] {
347             "android.preference.PreferenceActivity",
348             "java.**",
349             "org.kxml2.io.KXmlParser",
350             "org.xmlpull.**",
351             "sun.**",
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         "android.graphics.FontFamily#mBuilderPtr",
362         "android.graphics.Typeface#DEFAULT_FAMILY",
363         "android.graphics.Typeface#sDynamicTypefaceCache",
364         "android.graphics.drawable.AdaptiveIconDrawable#sMask",
365         "android.graphics.drawable.DrawableInflater#mRes",
366         "android.animation.PropertyValuesHolder#sSetterPropertyMap",
367         "android.animation.PropertyValuesHolder#sGetterPropertyMap",
368         "android.animation.PropertyValuesHolder$IntPropertyValuesHolder#sJNISetterPropertyMap",
369         "android.animation.PropertyValuesHolder$FloatPropertyValuesHolder#sJNISetterPropertyMap",
370         "android.animation.PropertyValuesHolder$MultiFloatValuesHolder#sJNISetterPropertyMap",
371         "android.animation.PropertyValuesHolder$MultiIntValuesHolder#sJNISetterPropertyMap",
372     };
373 
374     /**
375      * List of classes to be promoted to public visibility. Prefer using PROMOTED_FIELDS to this
376      * if possible.
377      */
378     private final static String[] PROMOTED_CLASSES = new String[] {
379     };
380 
381     /**
382      * List of classes for which the methods returning them should be deleted.
383      * The array contains a list of null terminated section starting with the name of the class
384      * to rename in which the methods are deleted, followed by a list of return types identifying
385      * the methods to delete.
386      */
387     private final static String[] DELETE_RETURNS =
388         new String[] {
389             null };                         // separator, for next class/methods list.
390 
391     private final static Map<String, InjectMethodRunnable> INJECTED_METHODS =
392             new HashMap<String, InjectMethodRunnable>(1) {{
393                 put("android.content.Context",
394                         InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER);
395             }};
396 }
397