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.layoutlib.bridge.android;
18 
19 import com.android.SdkConstants;
20 import com.android.ide.common.rendering.api.AssetRepository;
21 import com.android.ide.common.rendering.api.ILayoutPullParser;
22 import com.android.ide.common.rendering.api.LayoutLog;
23 import com.android.ide.common.rendering.api.LayoutlibCallback;
24 import com.android.ide.common.rendering.api.RenderResources;
25 import com.android.ide.common.rendering.api.ResourceReference;
26 import com.android.ide.common.rendering.api.ResourceValue;
27 import com.android.ide.common.rendering.api.StyleResourceValue;
28 import com.android.layoutlib.bridge.Bridge;
29 import com.android.layoutlib.bridge.BridgeConstants;
30 import com.android.layoutlib.bridge.android.view.WindowManagerImpl;
31 import com.android.layoutlib.bridge.impl.ParserFactory;
32 import com.android.layoutlib.bridge.impl.Stack;
33 import com.android.resources.ResourceType;
34 import com.android.util.Pair;
35 import com.android.util.PropertiesMap;
36 import com.android.util.PropertiesMap.Property;
37 
38 import org.xmlpull.v1.XmlPullParser;
39 import org.xmlpull.v1.XmlPullParserException;
40 
41 import android.annotation.NonNull;
42 import android.annotation.Nullable;
43 import android.content.BroadcastReceiver;
44 import android.content.ComponentName;
45 import android.content.ContentResolver;
46 import android.content.Context;
47 import android.content.ContextWrapper;
48 import android.content.Intent;
49 import android.content.IntentFilter;
50 import android.content.IntentSender;
51 import android.content.ServiceConnection;
52 import android.content.SharedPreferences;
53 import android.content.pm.ApplicationInfo;
54 import android.content.pm.PackageManager;
55 import android.content.res.AssetManager;
56 import android.content.res.BridgeAssetManager;
57 import android.content.res.BridgeTypedArray;
58 import android.content.res.Configuration;
59 import android.content.res.Resources;
60 import android.content.res.Resources.Theme;
61 import android.content.res.Resources_Delegate;
62 import android.database.DatabaseErrorHandler;
63 import android.database.sqlite.SQLiteDatabase;
64 import android.database.sqlite.SQLiteDatabase.CursorFactory;
65 import android.graphics.Bitmap;
66 import android.graphics.drawable.Drawable;
67 import android.hardware.display.DisplayManager;
68 import android.net.Uri;
69 import android.os.Build.VERSION_CODES;
70 import android.os.Bundle;
71 import android.os.Handler;
72 import android.os.IBinder;
73 import android.os.IInterface;
74 import android.os.Looper;
75 import android.os.Parcel;
76 import android.os.PowerManager;
77 import android.os.RemoteException;
78 import android.os.ResultReceiver;
79 import android.os.UserHandle;
80 import android.util.AttributeSet;
81 import android.util.DisplayMetrics;
82 import android.util.TypedValue;
83 import android.view.BridgeInflater;
84 import android.view.Display;
85 import android.view.DisplayAdjustments;
86 import android.view.LayoutInflater;
87 import android.view.View;
88 import android.view.ViewGroup;
89 import android.view.WindowManager;
90 import android.view.accessibility.AccessibilityManager;
91 import android.view.textservice.TextServicesManager;
92 
93 import java.io.File;
94 import java.io.FileDescriptor;
95 import java.io.FileInputStream;
96 import java.io.FileNotFoundException;
97 import java.io.FileOutputStream;
98 import java.io.IOException;
99 import java.io.InputStream;
100 import java.util.ArrayList;
101 import java.util.HashMap;
102 import java.util.IdentityHashMap;
103 import java.util.List;
104 import java.util.Map;
105 
106 import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
107 
108 /**
109  * Custom implementation of Context/Activity to handle non compiled resources.
110  */
111 @SuppressWarnings("deprecation")  // For use of Pair.
112 public final class BridgeContext extends Context {
113 
114     /** The map adds cookies to each view so that IDE can link xml tags to views. */
115     private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
116     /**
117      * In some cases, when inflating an xml, some objects are created. Then later, the objects are
118      * converted to views. This map stores the mapping from objects to cookies which can then be
119      * used to populate the mViewKeyMap.
120      */
121     private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
122     private final BridgeAssetManager mAssets;
123     private Resources mSystemResources;
124     private final Object mProjectKey;
125     private final DisplayMetrics mMetrics;
126     private final RenderResources mRenderResources;
127     private final Configuration mConfig;
128     private final ApplicationInfo mApplicationInfo;
129     private final LayoutlibCallback mLayoutlibCallback;
130     private final WindowManager mWindowManager;
131     private final DisplayManager mDisplayManager;
132     private final HashMap<View, Integer> mScrollYPos = new HashMap<>();
133     private final HashMap<View, Integer> mScrollXPos = new HashMap<>();
134 
135     private Resources.Theme mTheme;
136 
137     private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>();
138 
139     // maps for dynamically generated id representing style objects (StyleResourceValue)
140     @Nullable
141     private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
142     private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
143     private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
144 
145     // cache for TypedArray generated from StyleResourceValue object
146     private TypedArrayCache mTypedArrayCache;
147     private BridgeInflater mBridgeInflater;
148 
149     private BridgeContentResolver mContentResolver;
150 
151     private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
152     private SharedPreferences mSharedPreferences;
153     private ClassLoader mClassLoader;
154     private IBinder mBinder;
155     private PackageManager mPackageManager;
156 
157     /**
158      * Some applications that target both pre API 17 and post API 17, set the newer attrs to
159      * reference the older ones. For example, android:paddingStart will resolve to
160      * android:paddingLeft. This way the apps need to only define paddingLeft at any other place.
161      * This a map from value to attribute name. Warning for missing references shouldn't be logged
162      * if value and attr name pair is the same as an entry in this map.
163      */
164     private static Map<String, String> RTL_ATTRS = new HashMap<>(10);
165 
166     static {
167         RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart");
168         RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd");
169         RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart");
170         RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd");
171         RTL_ATTRS.put("?android:attr/layout_toLeftOf", "layout_toStartOf");
172         RTL_ATTRS.put("?android:attr/layout_toRightOf", "layout_toEndOf");
173         RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart");
174         RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd");
175         RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart");
176         RTL_ATTRS.put("?android:attr/drawableRight", "drawableEnd");
177     }
178 
179     /**
180      * @param projectKey An Object identifying the project. This is used for the cache mechanism.
181      * @param metrics the {@link DisplayMetrics}.
182      * @param renderResources the configured resources (both framework and projects) for this
183      * render.
184      * @param config the Configuration object for this render.
185      * @param targetSdkVersion the targetSdkVersion of the application.
186      */
BridgeContext(Object projectKey, DisplayMetrics metrics, RenderResources renderResources, AssetRepository assets, LayoutlibCallback layoutlibCallback, Configuration config, int targetSdkVersion, boolean hasRtlSupport)187     public BridgeContext(Object projectKey, DisplayMetrics metrics,
188             RenderResources renderResources,
189             AssetRepository assets,
190             LayoutlibCallback layoutlibCallback,
191             Configuration config,
192             int targetSdkVersion,
193             boolean hasRtlSupport) {
194         mProjectKey = projectKey;
195         mMetrics = metrics;
196         mLayoutlibCallback = layoutlibCallback;
197 
198         mRenderResources = renderResources;
199         mConfig = config;
200         AssetManager systemAssetManager = AssetManager.getSystem();
201         if (systemAssetManager instanceof BridgeAssetManager) {
202             mAssets = (BridgeAssetManager) systemAssetManager;
203         } else {
204             throw new AssertionError("Creating BridgeContext without initializing Bridge");
205         }
206         mAssets.setAssetRepository(assets);
207 
208         mApplicationInfo = new ApplicationInfo();
209         mApplicationInfo.targetSdkVersion = targetSdkVersion;
210         if (hasRtlSupport) {
211             mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL;
212         }
213 
214         mWindowManager = new WindowManagerImpl(mMetrics);
215         mDisplayManager = new DisplayManager(this);
216     }
217 
218     /**
219      * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its
220      * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}.
221      *
222      * @see #disposeResources()
223      */
initResources()224     public void initResources() {
225         AssetManager assetManager = AssetManager.getSystem();
226 
227         mSystemResources = Resources_Delegate.initSystem(
228                 this,
229                 assetManager,
230                 mMetrics,
231                 mConfig,
232                 mLayoutlibCallback);
233         mTheme = mSystemResources.newTheme();
234     }
235 
236     /**
237      * Disposes the {@link Resources} singleton.
238      */
disposeResources()239     public void disposeResources() {
240         Resources_Delegate.disposeSystem();
241     }
242 
setBridgeInflater(BridgeInflater inflater)243     public void setBridgeInflater(BridgeInflater inflater) {
244         mBridgeInflater = inflater;
245     }
246 
addViewKey(View view, Object viewKey)247     public void addViewKey(View view, Object viewKey) {
248         mViewKeyMap.put(view, viewKey);
249     }
250 
getViewKey(View view)251     public Object getViewKey(View view) {
252         return mViewKeyMap.get(view);
253     }
254 
addCookie(Object o, Object cookie)255     public void addCookie(Object o, Object cookie) {
256         mViewKeyHelpMap.put(o, cookie);
257     }
258 
getCookie(Object o)259     public Object getCookie(Object o) {
260         return mViewKeyHelpMap.get(o);
261     }
262 
getProjectKey()263     public Object getProjectKey() {
264         return mProjectKey;
265     }
266 
getMetrics()267     public DisplayMetrics getMetrics() {
268         return mMetrics;
269     }
270 
getLayoutlibCallback()271     public LayoutlibCallback getLayoutlibCallback() {
272         return mLayoutlibCallback;
273     }
274 
getRenderResources()275     public RenderResources getRenderResources() {
276         return mRenderResources;
277     }
278 
getDefaultProperties()279     public Map<Object, PropertiesMap> getDefaultProperties() {
280         return mDefaultPropMaps;
281     }
282 
getConfiguration()283     public Configuration getConfiguration() {
284         return mConfig;
285     }
286 
287     /**
288      * Adds a parser to the stack.
289      * @param parser the parser to add.
290      */
pushParser(BridgeXmlBlockParser parser)291     public void pushParser(BridgeXmlBlockParser parser) {
292         if (ParserFactory.LOG_PARSER) {
293             System.out.println("PUSH " + parser.getParser().toString());
294         }
295         mParserStack.push(parser);
296     }
297 
298     /**
299      * Removes the parser at the top of the stack
300      */
popParser()301     public void popParser() {
302         BridgeXmlBlockParser parser = mParserStack.pop();
303         if (ParserFactory.LOG_PARSER) {
304             System.out.println("POPD " + parser.getParser().toString());
305         }
306     }
307 
308     /**
309      * Returns the current parser at the top the of the stack.
310      * @return a parser or null.
311      */
getCurrentParser()312     public BridgeXmlBlockParser getCurrentParser() {
313         return mParserStack.peek();
314     }
315 
316     /**
317      * Returns the previous parser.
318      * @return a parser or null if there isn't any previous parser
319      */
getPreviousParser()320     public BridgeXmlBlockParser getPreviousParser() {
321         if (mParserStack.size() < 2) {
322             return null;
323         }
324         return mParserStack.get(mParserStack.size() - 2);
325     }
326 
resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs)327     public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
328         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId);
329         boolean isFrameworkRes = true;
330         if (resourceInfo == null) {
331             resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
332             isFrameworkRes = false;
333         }
334 
335         if (resourceInfo == null) {
336             return false;
337         }
338 
339         ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(),
340                 isFrameworkRes);
341         if (resolveRefs) {
342             value = mRenderResources.resolveResValue(value);
343         }
344 
345         if (value == null) {
346             // unable to find the attribute.
347             return false;
348         }
349 
350         // check if this is a style resource
351         if (value instanceof StyleResourceValue) {
352             // get the id that will represent this style.
353             outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value);
354             return true;
355         }
356 
357         int a;
358         // if this is a framework value.
359         if (value.isFramework()) {
360             // look for idName in the android R classes.
361             // use 0 a default res value as it's not a valid id value.
362             a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
363         } else {
364             // look for idName in the project R class.
365             // use 0 a default res value as it's not a valid id value.
366             a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
367         }
368 
369         if (a != 0) {
370             outValue.resourceId = a;
371             return true;
372         }
373 
374         return false;
375     }
376 
377 
resolveId(int id)378     public ResourceReference resolveId(int id) {
379         // first get the String related to this id in the framework
380         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
381 
382         if (resourceInfo != null) {
383             return new ResourceReference(resourceInfo.getSecond(), true);
384         }
385 
386         // didn't find a match in the framework? look in the project.
387         if (mLayoutlibCallback != null) {
388             resourceInfo = mLayoutlibCallback.resolveResourceId(id);
389 
390             if (resourceInfo != null) {
391                 return new ResourceReference(resourceInfo.getSecond(), false);
392             }
393         }
394 
395         // The base value for R.style is 0x01030000 and the custom style is 0x02030000.
396         // So, if the second byte is 03, it's probably a style.
397         if ((id >> 16 & 0xFF) == 0x03) {
398             return getStyleByDynamicId(id);
399         }
400         return null;
401     }
402 
inflateView(ResourceReference resource, ViewGroup parent, boolean attachToRoot, boolean skipCallbackParser)403     public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent,
404             boolean attachToRoot, boolean skipCallbackParser) {
405         boolean isPlatformLayout = resource.isFramework();
406 
407         if (!isPlatformLayout && !skipCallbackParser) {
408             // check if the project callback can provide us with a custom parser.
409             ILayoutPullParser parser = getParser(resource);
410 
411             if (parser != null) {
412                 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
413                         this, resource.isFramework());
414                 try {
415                     pushParser(blockParser);
416                     return Pair.of(
417                             mBridgeInflater.inflate(blockParser, parent, attachToRoot),
418                             Boolean.TRUE);
419                 } finally {
420                     popParser();
421                 }
422             }
423         }
424 
425         ResourceValue resValue;
426         if (resource instanceof ResourceValue) {
427             resValue = (ResourceValue) resource;
428         } else {
429             if (isPlatformLayout) {
430                 resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT,
431                         resource.getName());
432             } else {
433                 resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT,
434                         resource.getName());
435             }
436         }
437 
438         if (resValue != null) {
439 
440             File xml = new File(resValue.getValue());
441             if (xml.isFile()) {
442                 // we need to create a pull parser around the layout XML file, and then
443                 // give that to our XmlBlockParser
444                 try {
445                     XmlPullParser parser = ParserFactory.create(xml, true);
446 
447                     // set the resource ref to have correct view cookies
448                     mBridgeInflater.setResourceReference(resource);
449 
450                     BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
451                             this, resource.isFramework());
452                     try {
453                         pushParser(blockParser);
454                         return Pair.of(
455                                 mBridgeInflater.inflate(blockParser, parent, attachToRoot),
456                                 Boolean.FALSE);
457                     } finally {
458                         popParser();
459                     }
460                 } catch (XmlPullParserException e) {
461                     Bridge.getLog().error(LayoutLog.TAG_BROKEN,
462                             "Failed to configure parser for " + xml, e, null /*data*/);
463                     // we'll return null below.
464                 } catch (FileNotFoundException e) {
465                     // this shouldn't happen since we check above.
466                 } finally {
467                     mBridgeInflater.setResourceReference(null);
468                 }
469             } else {
470                 Bridge.getLog().error(LayoutLog.TAG_BROKEN,
471                         String.format("File %s is missing!", xml), null);
472             }
473         } else {
474             Bridge.getLog().error(LayoutLog.TAG_BROKEN,
475                     String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "",
476                             resource.getName()), null);
477         }
478 
479         return Pair.of(null, Boolean.FALSE);
480     }
481 
482     @SuppressWarnings("deprecation")
getParser(ResourceReference resource)483     private ILayoutPullParser getParser(ResourceReference resource) {
484         ILayoutPullParser parser;
485         if (resource instanceof ResourceValue) {
486             parser = mLayoutlibCallback.getParser((ResourceValue) resource);
487         } else {
488             parser = mLayoutlibCallback.getParser(resource.getName());
489         }
490         return parser;
491     }
492 
493     // ------------ Context methods
494 
495     @Override
getResources()496     public Resources getResources() {
497         return mSystemResources;
498     }
499 
500     @Override
getTheme()501     public Theme getTheme() {
502         return mTheme;
503     }
504 
505     @Override
getClassLoader()506     public ClassLoader getClassLoader() {
507         // The documentation for this method states that it should return a class loader one can
508         // use to retrieve classes in this package. However, when called by LayoutInflater, we do
509         // not want the class loader to return app's custom views.
510         // This is so that the IDE can instantiate the custom views and also generate proper error
511         // messages in case of failure. This also enables the IDE to fallback to MockView in case
512         // there's an exception thrown when trying to inflate the custom view.
513         // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to
514         // replace invocations of this method to a new method: getFrameworkClassLoader(). Also,
515         // the method is injected into Context. The implementation of getFrameworkClassLoader() is:
516         // "return getClass().getClassLoader();". This means that when LayoutInflater asks for
517         // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have
518         // access to the apps's custom views.
519         // This method can now return the right ClassLoader, which CustomViews can use to do the
520         // right thing.
521         if (mClassLoader == null) {
522             mClassLoader = new ClassLoader(getClass().getClassLoader()) {
523                 @Override
524                 protected Class<?> findClass(String name) throws ClassNotFoundException {
525                     for (String prefix : BridgeInflater.getClassPrefixList()) {
526                         if (name.startsWith(prefix)) {
527                             // These are framework classes and should not be loaded from the app.
528                             throw new ClassNotFoundException(name + " not found");
529                         }
530                     }
531                     return BridgeContext.this.mLayoutlibCallback.findClass(name);
532                 }
533             };
534         }
535         return mClassLoader;
536     }
537 
538     @Override
getSystemService(String service)539     public Object getSystemService(String service) {
540         if (LAYOUT_INFLATER_SERVICE.equals(service)) {
541             return mBridgeInflater;
542         }
543 
544         if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) {
545             // we need to return a valid service to avoid NPE
546             return TextServicesManager.getInstance();
547         }
548 
549         if (WINDOW_SERVICE.equals(service)) {
550             return mWindowManager;
551         }
552 
553         // needed by SearchView
554         if (INPUT_METHOD_SERVICE.equals(service)) {
555             return null;
556         }
557 
558         if (POWER_SERVICE.equals(service)) {
559             return new PowerManager(this, new BridgePowerManager(), new Handler());
560         }
561 
562         if (DISPLAY_SERVICE.equals(service)) {
563             return mDisplayManager;
564         }
565 
566         if (ACCESSIBILITY_SERVICE.equals(service)) {
567             return AccessibilityManager.getInstance(this);
568         }
569 
570         throw new UnsupportedOperationException("Unsupported Service: " + service);
571     }
572 
573     @Override
getSystemServiceName(Class<?> serviceClass)574     public String getSystemServiceName(Class<?> serviceClass) {
575         if (serviceClass.equals(LayoutInflater.class)) {
576             return LAYOUT_INFLATER_SERVICE;
577         }
578 
579         if (serviceClass.equals(TextServicesManager.class)) {
580             return TEXT_SERVICES_MANAGER_SERVICE;
581         }
582 
583         if (serviceClass.equals(WindowManager.class)) {
584             return WINDOW_SERVICE;
585         }
586 
587         if (serviceClass.equals(PowerManager.class)) {
588             return POWER_SERVICE;
589         }
590 
591         if (serviceClass.equals(DisplayManager.class)) {
592             return DISPLAY_SERVICE;
593         }
594 
595         if (serviceClass.equals(AccessibilityManager.class)) {
596             return ACCESSIBILITY_SERVICE;
597         }
598 
599         throw new UnsupportedOperationException("Unsupported Service: " + serviceClass);
600     }
601 
602     @Override
obtainStyledAttributes(int[] attrs)603     public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
604         return obtainStyledAttributes(0, attrs);
605     }
606 
607     @Override
obtainStyledAttributes(int resId, int[] attrs)608     public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs)
609             throws Resources.NotFoundException {
610         StyleResourceValue style = null;
611         // get the StyleResourceValue based on the resId;
612         if (resId != 0) {
613             style = getStyleByDynamicId(resId);
614 
615             if (style == null) {
616                 // In some cases, style may not be a dynamic id, so we do a full search.
617                 ResourceReference ref = resolveId(resId);
618                 if (ref != null) {
619                     style = mRenderResources.getStyle(ref.getName(), ref.isFramework());
620                 }
621             }
622 
623             if (style == null) {
624                 throw new Resources.NotFoundException();
625             }
626         }
627 
628         if (mTypedArrayCache == null) {
629             mTypedArrayCache = new TypedArrayCache();
630         }
631 
632         List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
633 
634         Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair =
635                 mTypedArrayCache.get(attrs, currentThemes, resId);
636 
637         if (typeArrayAndPropertiesPair == null) {
638             typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs);
639             mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair);
640         }
641         // Add value to defaultPropsMap if needed
642         if (typeArrayAndPropertiesPair.getSecond() != null) {
643             BridgeXmlBlockParser parser = getCurrentParser();
644             Object key = parser != null ? parser.getViewCookie() : null;
645             if (key != null) {
646                 PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
647                 if (defaultPropMap == null) {
648                     defaultPropMap = typeArrayAndPropertiesPair.getSecond();
649                     mDefaultPropMaps.put(key, defaultPropMap);
650                 } else {
651                     defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond());
652                 }
653             }
654         }
655         return typeArrayAndPropertiesPair.getFirst();
656     }
657 
658     @Override
obtainStyledAttributes(AttributeSet set, int[] attrs)659     public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
660         return obtainStyledAttributes(set, attrs, 0, 0);
661     }
662 
663     @Override
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)664     public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
665             int defStyleAttr, int defStyleRes) {
666 
667         PropertiesMap defaultPropMap = null;
668         boolean isPlatformFile = true;
669 
670         // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
671         if (set instanceof BridgeXmlBlockParser) {
672             BridgeXmlBlockParser parser;
673             parser = (BridgeXmlBlockParser)set;
674 
675             isPlatformFile = parser.isPlatformFile();
676 
677             Object key = parser.getViewCookie();
678             if (key != null) {
679                 defaultPropMap = mDefaultPropMaps.get(key);
680                 if (defaultPropMap == null) {
681                     defaultPropMap = new PropertiesMap();
682                     mDefaultPropMaps.put(key, defaultPropMap);
683                 }
684             }
685 
686         } else if (set instanceof BridgeLayoutParamsMapAttributes) {
687             // this is only for temp layout params generated dynamically, so this is never
688             // platform content.
689             isPlatformFile = false;
690         } else if (set != null) { // null parser is ok
691             // really this should not be happening since its instantiated in Bridge
692             Bridge.getLog().error(LayoutLog.TAG_BROKEN,
693                     "Parser is not a BridgeXmlBlockParser!", null);
694             return null;
695         }
696 
697         List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
698 
699         BridgeTypedArray ta =
700                 Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
701 
702         // look for a custom style.
703         String customStyle = null;
704         if (set != null) {
705             customStyle = set.getAttributeValue(null, "style");
706         }
707 
708         StyleResourceValue customStyleValues = null;
709         if (customStyle != null) {
710             ResourceValue item = mRenderResources.findResValue(customStyle,
711                     isPlatformFile /*forceFrameworkOnly*/);
712 
713             // resolve it in case it links to something else
714             item = mRenderResources.resolveResValue(item);
715 
716             if (item instanceof StyleResourceValue) {
717                 customStyleValues = (StyleResourceValue)item;
718             }
719         }
720 
721         // resolve the defStyleAttr value into a IStyleResourceValue
722         StyleResourceValue defStyleValues = null;
723 
724         if (defStyleAttr != 0) {
725             // get the name from the int.
726             Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
727 
728             if (defStyleAttribute == null) {
729                 // This should be rare. Happens trying to map R.style.foo to @style/foo fails.
730                 // This will happen if the user explicitly used a non existing int value for
731                 // defStyleAttr or there's something wrong with the project structure/build.
732                 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
733                         "Failed to find the style corresponding to the id " + defStyleAttr, null);
734             } else {
735                 String defStyleName = defStyleAttribute.getFirst();
736 
737                 // look for the style in the current theme, and its parent:
738                 ResourceValue item = mRenderResources.findItemInTheme(defStyleName,
739                         defStyleAttribute.getSecond());
740 
741                 if (item != null) {
742                     // item is a reference to a style entry. Search for it.
743                     item = mRenderResources.findResValue(item.getValue(), item.isFramework());
744                     item = mRenderResources.resolveResValue(item);
745                     if (item instanceof StyleResourceValue) {
746                         defStyleValues = (StyleResourceValue) item;
747                     }
748                     if (defaultPropMap != null) {
749                         if (defStyleAttribute.getSecond()) {
750                             defStyleName = "android:" + defStyleName;
751                         }
752                         defaultPropMap.put("style", new Property(defStyleName, item.getValue()));
753                     }
754                 } else {
755                     Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
756                             String.format(
757                                     "Failed to find style '%s' in current theme",
758                                     defStyleAttribute.getFirst()),
759                             null);
760                 }
761             }
762         } else if (defStyleRes != 0) {
763             StyleResourceValue item = getStyleByDynamicId(defStyleRes);
764             if (item != null) {
765                 defStyleValues = item;
766             } else {
767                 boolean isFrameworkRes = true;
768                 Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
769                 if (value == null) {
770                     value = mLayoutlibCallback.resolveResourceId(defStyleRes);
771                     isFrameworkRes = false;
772                 }
773 
774                 if (value != null) {
775                     if ((value.getFirst() == ResourceType.STYLE)) {
776                         // look for the style in all resources:
777                         item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes);
778                         if (item != null) {
779                             if (defaultPropMap != null) {
780                                 String name = item.getName();
781                                 defaultPropMap.put("style", new Property(name, name));
782                             }
783 
784                             defStyleValues = item;
785                         } else {
786                             Bridge.getLog().error(null,
787                                     String.format(
788                                             "Style with id 0x%x (resolved to '%s') does not exist.",
789                                             defStyleRes, value.getSecond()),
790                                     null);
791                         }
792                     } else {
793                         Bridge.getLog().error(null,
794                                 String.format(
795                                         "Resource id 0x%x is not of type STYLE (instead %s)",
796                                         defStyleRes, value.getFirst().toString()),
797                                 null);
798                     }
799                 } else {
800                     Bridge.getLog().error(null,
801                             String.format(
802                                     "Failed to find style with id 0x%x in current theme",
803                                     defStyleRes),
804                             null);
805                 }
806             }
807         }
808 
809         String appNamespace = mLayoutlibCallback.getNamespace();
810 
811         if (attributeList != null) {
812             for (int index = 0 ; index < attributeList.size() ; index++) {
813                 Pair<String, Boolean> attribute = attributeList.get(index);
814 
815                 if (attribute == null) {
816                     continue;
817                 }
818 
819                 String attrName = attribute.getFirst();
820                 boolean frameworkAttr = attribute.getSecond();
821                 String value = null;
822                 if (set != null) {
823                     value = set.getAttributeValue(
824                             frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace,
825                                     attrName);
826 
827                     // if this is an app attribute, and the first get fails, try with the
828                     // new res-auto namespace as well
829                     if (!frameworkAttr && value == null) {
830                         value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
831                     }
832                 }
833 
834                 // if there's no direct value for this attribute in the XML, we look for default
835                 // values in the widget defStyle, and then in the theme.
836                 if (value == null) {
837                     ResourceValue resValue = null;
838 
839                     // look for the value in the custom style first (and its parent if needed)
840                     if (customStyleValues != null) {
841                         resValue = mRenderResources.findItemInStyle(customStyleValues,
842                                 attrName, frameworkAttr);
843                     }
844 
845                     // then look for the value in the default Style (and its parent if needed)
846                     if (resValue == null && defStyleValues != null) {
847                         resValue = mRenderResources.findItemInStyle(defStyleValues,
848                                 attrName, frameworkAttr);
849                     }
850 
851                     // if the item is not present in the defStyle, we look in the main theme (and
852                     // its parent themes)
853                     if (resValue == null) {
854                         resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
855                     }
856 
857                     // if we found a value, we make sure this doesn't reference another value.
858                     // So we resolve it.
859                     if (resValue != null) {
860                         String preResolve = resValue.getValue();
861                         resValue = mRenderResources.resolveResValue(resValue);
862 
863                         if (defaultPropMap != null) {
864                             defaultPropMap.put(
865                                     frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName :
866                                             attrName,
867                                     new Property(preResolve, resValue.getValue()));
868                         }
869 
870                         // If the value is a reference to another theme attribute that doesn't
871                         // exist, we should log a warning and omit it.
872                         String val = resValue.getValue();
873                         if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
874                             if (!attrName.equals(RTL_ATTRS.get(val)) ||
875                                     getApplicationInfo().targetSdkVersion <
876                                             VERSION_CODES.JELLY_BEAN_MR1) {
877                                 // Only log a warning if the referenced value isn't one of the RTL
878                                 // attributes, or the app targets old API.
879                                 Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
880                                         String.format("Failed to find '%s' in current theme.", val),
881                                         val);
882                             }
883                             resValue = null;
884                         }
885                     }
886 
887                     ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
888                 } else {
889                     // there is a value in the XML, but we need to resolve it in case it's
890                     // referencing another resource or a theme value.
891                     ta.bridgeSetValue(index, attrName, frameworkAttr,
892                             mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
893                 }
894             }
895         }
896 
897         ta.sealArray();
898 
899         return ta;
900     }
901 
902     @Override
getMainLooper()903     public Looper getMainLooper() {
904         return Looper.myLooper();
905     }
906 
907 
908     @Override
getPackageName()909     public String getPackageName() {
910         if (mApplicationInfo.packageName == null) {
911             mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE);
912         }
913         return mApplicationInfo.packageName;
914     }
915 
916     @Override
getPackageManager()917     public PackageManager getPackageManager() {
918         if (mPackageManager == null) {
919             mPackageManager = new BridgePackageManager();
920         }
921         return mPackageManager;
922     }
923 
924     // ------------- private new methods
925 
926     /**
927      * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
928      * values found in the given style. If no style is specified, the default theme, along with the
929      * styles applied to it are used.
930      *
931      * @see #obtainStyledAttributes(int, int[])
932      */
createStyleBasedTypedArray( @ullable StyleResourceValue style, int[] attrs)933     private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
934             @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
935         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
936 
937         BridgeTypedArray ta =
938                 Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
939 
940         PropertiesMap defaultPropMap = new PropertiesMap();
941         // for each attribute, get its name so that we can search it in the style
942         for (int i = 0; i < attrs.length; i++) {
943             Pair<String, Boolean> attribute = attributes.get(i);
944 
945             if (attribute != null) {
946                 // look for the value in the given style
947                 ResourceValue resValue;
948                 String attrName = attribute.getFirst();
949                 boolean frameworkAttr = attribute.getSecond();
950                 if (style != null) {
951                     resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr);
952                 } else {
953                     resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
954                 }
955 
956                 if (resValue != null) {
957                     // Add it to defaultPropMap before resolving
958                     String preResolve = resValue.getValue();
959                     // resolve it to make sure there are no references left.
960                     resValue = mRenderResources.resolveResValue(resValue);
961                     ta.bridgeSetValue(i, attrName, frameworkAttr, resValue);
962                     defaultPropMap.put(
963                             frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName,
964                             new Property(preResolve, resValue.getValue()));
965                 }
966             }
967         }
968 
969         ta.sealArray();
970 
971         return Pair.of(ta, defaultPropMap);
972     }
973 
974     /**
975      * The input int[] attrs is a list of attributes. The returns a list of information about
976      * each attributes. The information is (name, isFramework)
977      * <p/>
978      *
979      * @param attrs An attribute array reference given to obtainStyledAttributes.
980      * @return List of attribute information.
981      */
searchAttrs(int[] attrs)982     private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
983         List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
984 
985         // for each attribute, get its name so that we can search it in the style
986         for (int attr : attrs) {
987             Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr);
988             boolean isFramework = false;
989             if (resolvedResource != null) {
990                 isFramework = true;
991             } else {
992                 resolvedResource = mLayoutlibCallback.resolveResourceId(attr);
993             }
994 
995             if (resolvedResource != null) {
996                 results.add(Pair.of(resolvedResource.getSecond(), isFramework));
997             } else {
998                 results.add(null);
999             }
1000         }
1001 
1002         return results;
1003     }
1004 
1005     /**
1006      * Searches for the attribute referenced by its internal id.
1007      *
1008      * @param attr An attribute reference given to obtainStyledAttributes such as defStyle.
1009      * @return A (name, isFramework) pair describing the attribute if found. Returns null
1010      *         if nothing is found.
1011      */
searchAttr(int attr)1012     private Pair<String, Boolean> searchAttr(int attr) {
1013         Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
1014         if (info != null) {
1015             return Pair.of(info.getSecond(), Boolean.TRUE);
1016         }
1017 
1018         info = mLayoutlibCallback.resolveResourceId(attr);
1019         if (info != null) {
1020             return Pair.of(info.getSecond(), Boolean.FALSE);
1021         }
1022 
1023         return null;
1024     }
1025 
getDynamicIdByStyle(StyleResourceValue resValue)1026     public int getDynamicIdByStyle(StyleResourceValue resValue) {
1027         if (mDynamicIdToStyleMap == null) {
1028             // create the maps.
1029             mDynamicIdToStyleMap = new HashMap<>();
1030             mStyleToDynamicIdMap = new HashMap<>();
1031         }
1032 
1033         // look for an existing id
1034         Integer id = mStyleToDynamicIdMap.get(resValue);
1035 
1036         if (id == null) {
1037             // generate a new id
1038             id = ++mDynamicIdGenerator;
1039 
1040             // and add it to the maps.
1041             mDynamicIdToStyleMap.put(id, resValue);
1042             mStyleToDynamicIdMap.put(resValue, id);
1043         }
1044 
1045         return id;
1046     }
1047 
getStyleByDynamicId(int i)1048     private StyleResourceValue getStyleByDynamicId(int i) {
1049         if (mDynamicIdToStyleMap != null) {
1050             return mDynamicIdToStyleMap.get(i);
1051         }
1052 
1053         return null;
1054     }
1055 
getFrameworkResourceValue(ResourceType resType, String resName, int defValue)1056     public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) {
1057         if (getRenderResources().getFrameworkResource(resType, resName) != null) {
1058             // Bridge.getResourceId creates a new resource id if an existing one isn't found. So,
1059             // we check for the existence of the resource before calling it.
1060             return Bridge.getResourceId(resType, resName);
1061         }
1062 
1063         return defValue;
1064     }
1065 
getProjectResourceValue(ResourceType resType, String resName, int defValue)1066     public int getProjectResourceValue(ResourceType resType, String resName, int defValue) {
1067         // getResourceId creates a new resource id if an existing resource id isn't found. So, we
1068         // check for the existence of the resource before calling it.
1069         if (getRenderResources().getProjectResource(resType, resName) != null) {
1070             if (mLayoutlibCallback != null) {
1071                 Integer value = mLayoutlibCallback.getResourceId(resType, resName);
1072                 if (value != null) {
1073                     return value;
1074                 }
1075             }
1076         }
1077 
1078         return defValue;
1079     }
1080 
getBaseContext(Context context)1081     public static Context getBaseContext(Context context) {
1082         while (context instanceof ContextWrapper) {
1083             context = ((ContextWrapper) context).getBaseContext();
1084         }
1085         return context;
1086     }
1087 
getBinder()1088     public IBinder getBinder() {
1089         if (mBinder == null) {
1090             // create a dummy binder. We only need it be not null.
1091             mBinder = new IBinder() {
1092                 @Override
1093                 public String getInterfaceDescriptor() throws RemoteException {
1094                     return null;
1095                 }
1096 
1097                 @Override
1098                 public boolean pingBinder() {
1099                     return false;
1100                 }
1101 
1102                 @Override
1103                 public boolean isBinderAlive() {
1104                     return false;
1105                 }
1106 
1107                 @Override
1108                 public IInterface queryLocalInterface(String descriptor) {
1109                     return null;
1110                 }
1111 
1112                 @Override
1113                 public void dump(FileDescriptor fd, String[] args) throws RemoteException {
1114 
1115                 }
1116 
1117                 @Override
1118                 public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
1119 
1120                 }
1121 
1122                 @Override
1123                 public boolean transact(int code, Parcel data, Parcel reply, int flags)
1124                         throws RemoteException {
1125                     return false;
1126                 }
1127 
1128                 @Override
1129                 public void linkToDeath(DeathRecipient recipient, int flags)
1130                         throws RemoteException {
1131 
1132                 }
1133 
1134                 @Override
1135                 public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
1136                     return false;
1137                 }
1138 
1139                 @Override
1140                 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1141                   String[] args, ResultReceiver resultReceiver) {
1142                 }
1143             };
1144         }
1145         return mBinder;
1146     }
1147 
1148     //------------ NOT OVERRIDEN --------------------
1149 
1150     @Override
bindService(Intent arg0, ServiceConnection arg1, int arg2)1151     public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
1152         // pass
1153         return false;
1154     }
1155 
1156     @Override
checkCallingOrSelfPermission(String arg0)1157     public int checkCallingOrSelfPermission(String arg0) {
1158         // pass
1159         return 0;
1160     }
1161 
1162     @Override
checkCallingOrSelfUriPermission(Uri arg0, int arg1)1163     public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
1164         // pass
1165         return 0;
1166     }
1167 
1168     @Override
checkCallingPermission(String arg0)1169     public int checkCallingPermission(String arg0) {
1170         // pass
1171         return 0;
1172     }
1173 
1174     @Override
checkCallingUriPermission(Uri arg0, int arg1)1175     public int checkCallingUriPermission(Uri arg0, int arg1) {
1176         // pass
1177         return 0;
1178     }
1179 
1180     @Override
checkPermission(String arg0, int arg1, int arg2)1181     public int checkPermission(String arg0, int arg1, int arg2) {
1182         // pass
1183         return 0;
1184     }
1185 
1186     @Override
checkSelfPermission(String arg0)1187     public int checkSelfPermission(String arg0) {
1188         // pass
1189         return 0;
1190     }
1191 
1192     @Override
checkPermission(String arg0, int arg1, int arg2, IBinder arg3)1193     public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
1194         // pass
1195         return 0;
1196     }
1197 
1198     @Override
checkUriPermission(Uri arg0, int arg1, int arg2, int arg3)1199     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
1200         // pass
1201         return 0;
1202     }
1203 
1204     @Override
checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4)1205     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) {
1206         // pass
1207         return 0;
1208     }
1209 
1210     @Override
checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5)1211     public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
1212             int arg4, int arg5) {
1213         // pass
1214         return 0;
1215     }
1216 
1217     @Override
clearWallpaper()1218     public void clearWallpaper() {
1219         // pass
1220 
1221     }
1222 
1223     @Override
createPackageContext(String arg0, int arg1)1224     public Context createPackageContext(String arg0, int arg1) {
1225         // pass
1226         return null;
1227     }
1228 
1229     @Override
createPackageContextAsUser(String arg0, int arg1, UserHandle user)1230     public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
1231         // pass
1232         return null;
1233     }
1234 
1235     @Override
createConfigurationContext(Configuration overrideConfiguration)1236     public Context createConfigurationContext(Configuration overrideConfiguration) {
1237         // pass
1238         return null;
1239     }
1240 
1241     @Override
createDisplayContext(Display display)1242     public Context createDisplayContext(Display display) {
1243         // pass
1244         return null;
1245     }
1246 
1247     @Override
databaseList()1248     public String[] databaseList() {
1249         // pass
1250         return null;
1251     }
1252 
1253     @Override
createApplicationContext(ApplicationInfo application, int flags)1254     public Context createApplicationContext(ApplicationInfo application, int flags)
1255             throws PackageManager.NameNotFoundException {
1256         return null;
1257     }
1258 
1259     @Override
moveDatabaseFrom(Context sourceContext, String name)1260     public boolean moveDatabaseFrom(Context sourceContext, String name) {
1261         // pass
1262         return false;
1263     }
1264 
1265     @Override
deleteDatabase(String arg0)1266     public boolean deleteDatabase(String arg0) {
1267         // pass
1268         return false;
1269     }
1270 
1271     @Override
deleteFile(String arg0)1272     public boolean deleteFile(String arg0) {
1273         // pass
1274         return false;
1275     }
1276 
1277     @Override
enforceCallingOrSelfPermission(String arg0, String arg1)1278     public void enforceCallingOrSelfPermission(String arg0, String arg1) {
1279         // pass
1280 
1281     }
1282 
1283     @Override
enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2)1284     public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
1285             String arg2) {
1286         // pass
1287 
1288     }
1289 
1290     @Override
enforceCallingPermission(String arg0, String arg1)1291     public void enforceCallingPermission(String arg0, String arg1) {
1292         // pass
1293 
1294     }
1295 
1296     @Override
enforceCallingUriPermission(Uri arg0, int arg1, String arg2)1297     public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
1298         // pass
1299 
1300     }
1301 
1302     @Override
enforcePermission(String arg0, int arg1, int arg2, String arg3)1303     public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
1304         // pass
1305 
1306     }
1307 
1308     @Override
enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4)1309     public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
1310             String arg4) {
1311         // pass
1312 
1313     }
1314 
1315     @Override
enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6)1316     public void enforceUriPermission(Uri arg0, String arg1, String arg2,
1317             int arg3, int arg4, int arg5, String arg6) {
1318         // pass
1319 
1320     }
1321 
1322     @Override
fileList()1323     public String[] fileList() {
1324         // pass
1325         return null;
1326     }
1327 
1328     @Override
getAssets()1329     public BridgeAssetManager getAssets() {
1330         return mAssets;
1331     }
1332 
1333     @Override
getCacheDir()1334     public File getCacheDir() {
1335         // pass
1336         return null;
1337     }
1338 
1339     @Override
getCodeCacheDir()1340     public File getCodeCacheDir() {
1341         // pass
1342         return null;
1343     }
1344 
1345     @Override
getExternalCacheDir()1346     public File getExternalCacheDir() {
1347         // pass
1348         return null;
1349     }
1350 
1351     @Override
getContentResolver()1352     public ContentResolver getContentResolver() {
1353         if (mContentResolver == null) {
1354             mContentResolver = new BridgeContentResolver(this);
1355         }
1356         return mContentResolver;
1357     }
1358 
1359     @Override
getDatabasePath(String arg0)1360     public File getDatabasePath(String arg0) {
1361         // pass
1362         return null;
1363     }
1364 
1365     @Override
getDir(String arg0, int arg1)1366     public File getDir(String arg0, int arg1) {
1367         // pass
1368         return null;
1369     }
1370 
1371     @Override
getFileStreamPath(String arg0)1372     public File getFileStreamPath(String arg0) {
1373         // pass
1374         return null;
1375     }
1376 
1377     @Override
getSharedPreferencesPath(String name)1378     public File getSharedPreferencesPath(String name) {
1379         // pass
1380         return null;
1381     }
1382 
1383     @Override
getDataDir()1384     public File getDataDir() {
1385         // pass
1386         return null;
1387     }
1388 
1389     @Override
getFilesDir()1390     public File getFilesDir() {
1391         // pass
1392         return null;
1393     }
1394 
1395     @Override
getNoBackupFilesDir()1396     public File getNoBackupFilesDir() {
1397         // pass
1398         return null;
1399     }
1400 
1401     @Override
getExternalFilesDir(String type)1402     public File getExternalFilesDir(String type) {
1403         // pass
1404         return null;
1405     }
1406 
1407     @Override
getPackageCodePath()1408     public String getPackageCodePath() {
1409         // pass
1410         return null;
1411     }
1412 
1413     @Override
getBasePackageName()1414     public String getBasePackageName() {
1415         // pass
1416         return null;
1417     }
1418 
1419     @Override
getOpPackageName()1420     public String getOpPackageName() {
1421         // pass
1422         return null;
1423     }
1424 
1425     @Override
getApplicationInfo()1426     public ApplicationInfo getApplicationInfo() {
1427         return mApplicationInfo;
1428     }
1429 
1430     @Override
getPackageResourcePath()1431     public String getPackageResourcePath() {
1432         // pass
1433         return null;
1434     }
1435 
1436     @Override
getSharedPreferences(String arg0, int arg1)1437     public SharedPreferences getSharedPreferences(String arg0, int arg1) {
1438         if (mSharedPreferences == null) {
1439             mSharedPreferences = new BridgeSharedPreferences();
1440         }
1441         return mSharedPreferences;
1442     }
1443 
1444     @Override
getSharedPreferences(File arg0, int arg1)1445     public SharedPreferences getSharedPreferences(File arg0, int arg1) {
1446         if (mSharedPreferences == null) {
1447             mSharedPreferences = new BridgeSharedPreferences();
1448         }
1449         return mSharedPreferences;
1450     }
1451 
1452     @Override
moveSharedPreferencesFrom(Context sourceContext, String name)1453     public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
1454         // pass
1455         return false;
1456     }
1457 
1458     @Override
deleteSharedPreferences(String name)1459     public boolean deleteSharedPreferences(String name) {
1460         // pass
1461         return false;
1462     }
1463 
1464     @Override
getWallpaper()1465     public Drawable getWallpaper() {
1466         // pass
1467         return null;
1468     }
1469 
1470     @Override
getWallpaperDesiredMinimumWidth()1471     public int getWallpaperDesiredMinimumWidth() {
1472         return -1;
1473     }
1474 
1475     @Override
getWallpaperDesiredMinimumHeight()1476     public int getWallpaperDesiredMinimumHeight() {
1477         return -1;
1478     }
1479 
1480     @Override
grantUriPermission(String arg0, Uri arg1, int arg2)1481     public void grantUriPermission(String arg0, Uri arg1, int arg2) {
1482         // pass
1483 
1484     }
1485 
1486     @Override
openFileInput(String arg0)1487     public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
1488         // pass
1489         return null;
1490     }
1491 
1492     @Override
openFileOutput(String arg0, int arg1)1493     public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
1494         // pass
1495         return null;
1496     }
1497 
1498     @Override
openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2)1499     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
1500         // pass
1501         return null;
1502     }
1503 
1504     @Override
openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2, DatabaseErrorHandler arg3)1505     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
1506             CursorFactory arg2, DatabaseErrorHandler arg3) {
1507         // pass
1508         return null;
1509     }
1510 
1511     @Override
peekWallpaper()1512     public Drawable peekWallpaper() {
1513         // pass
1514         return null;
1515     }
1516 
1517     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1)1518     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
1519         // pass
1520         return null;
1521     }
1522 
1523     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3)1524     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
1525             String arg2, Handler arg3) {
1526         // pass
1527         return null;
1528     }
1529 
1530     @Override
registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3)1531     public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
1532             IntentFilter arg1, String arg2, Handler arg3) {
1533         // pass
1534         return null;
1535     }
1536 
1537     @Override
removeStickyBroadcast(Intent arg0)1538     public void removeStickyBroadcast(Intent arg0) {
1539         // pass
1540 
1541     }
1542 
1543     @Override
revokeUriPermission(Uri arg0, int arg1)1544     public void revokeUriPermission(Uri arg0, int arg1) {
1545         // pass
1546 
1547     }
1548 
1549     @Override
sendBroadcast(Intent arg0)1550     public void sendBroadcast(Intent arg0) {
1551         // pass
1552 
1553     }
1554 
1555     @Override
sendBroadcast(Intent arg0, String arg1)1556     public void sendBroadcast(Intent arg0, String arg1) {
1557         // pass
1558 
1559     }
1560 
1561     @Override
sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)1562     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
1563         // pass
1564 
1565     }
1566 
1567     @Override
sendBroadcast(Intent arg0, String arg1, Bundle arg2)1568     public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) {
1569         // pass
1570 
1571     }
1572 
1573     @Override
sendBroadcast(Intent intent, String receiverPermission, int appOp)1574     public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
1575         // pass
1576     }
1577 
1578     @Override
sendOrderedBroadcast(Intent arg0, String arg1)1579     public void sendOrderedBroadcast(Intent arg0, String arg1) {
1580         // pass
1581 
1582     }
1583 
1584     @Override
sendOrderedBroadcast(Intent arg0, String arg1, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1585     public void sendOrderedBroadcast(Intent arg0, String arg1,
1586             BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
1587             Bundle arg6) {
1588         // pass
1589 
1590     }
1591 
1592     @Override
sendOrderedBroadcast(Intent arg0, String arg1, Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1593     public void sendOrderedBroadcast(Intent arg0, String arg1,
1594             Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
1595             Bundle arg6) {
1596         // pass
1597 
1598     }
1599 
1600     @Override
sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1601     public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
1602             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
1603             String initialData, Bundle initialExtras) {
1604         // pass
1605     }
1606 
1607     @Override
sendBroadcastAsUser(Intent intent, UserHandle user)1608     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
1609         // pass
1610     }
1611 
1612     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)1613     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1614             String receiverPermission) {
1615         // pass
1616     }
1617 
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp)1618     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1619             String receiverPermission, int appOp) {
1620         // pass
1621     }
1622 
1623     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1624     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1625             String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
1626             int initialCode, String initialData, Bundle initialExtras) {
1627         // pass
1628     }
1629 
1630     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1631     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1632             String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
1633             Handler scheduler,
1634             int initialCode, String initialData, Bundle initialExtras) {
1635         // pass
1636     }
1637 
1638     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1639     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1640             String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
1641             Handler scheduler,
1642             int initialCode, String initialData, Bundle initialExtras) {
1643         // pass
1644     }
1645 
1646     @Override
sendStickyBroadcast(Intent arg0)1647     public void sendStickyBroadcast(Intent arg0) {
1648         // pass
1649 
1650     }
1651 
1652     @Override
sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1653     public void sendStickyOrderedBroadcast(Intent intent,
1654             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
1655            Bundle initialExtras) {
1656         // pass
1657     }
1658 
1659     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user)1660     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
1661         // pass
1662     }
1663 
1664     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options)1665     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
1666         // pass
1667     }
1668 
1669     @Override
sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1670     public void sendStickyOrderedBroadcastAsUser(Intent intent,
1671             UserHandle user, BroadcastReceiver resultReceiver,
1672             Handler scheduler, int initialCode, String initialData,
1673             Bundle initialExtras) {
1674         // pass
1675     }
1676 
1677     @Override
removeStickyBroadcastAsUser(Intent intent, UserHandle user)1678     public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
1679         // pass
1680     }
1681 
1682     @Override
setTheme(int arg0)1683     public void setTheme(int arg0) {
1684         // pass
1685 
1686     }
1687 
1688     @Override
setWallpaper(Bitmap arg0)1689     public void setWallpaper(Bitmap arg0) throws IOException {
1690         // pass
1691 
1692     }
1693 
1694     @Override
setWallpaper(InputStream arg0)1695     public void setWallpaper(InputStream arg0) throws IOException {
1696         // pass
1697 
1698     }
1699 
1700     @Override
startActivity(Intent arg0)1701     public void startActivity(Intent arg0) {
1702         // pass
1703     }
1704 
1705     @Override
startActivity(Intent arg0, Bundle arg1)1706     public void startActivity(Intent arg0, Bundle arg1) {
1707         // pass
1708     }
1709 
1710     @Override
startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)1711     public void startIntentSender(IntentSender intent,
1712             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
1713             throws IntentSender.SendIntentException {
1714         // pass
1715     }
1716 
1717     @Override
startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)1718     public void startIntentSender(IntentSender intent,
1719             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
1720             Bundle options) throws IntentSender.SendIntentException {
1721         // pass
1722     }
1723 
1724     @Override
startInstrumentation(ComponentName arg0, String arg1, Bundle arg2)1725     public boolean startInstrumentation(ComponentName arg0, String arg1,
1726             Bundle arg2) {
1727         // pass
1728         return false;
1729     }
1730 
1731     @Override
startService(Intent arg0)1732     public ComponentName startService(Intent arg0) {
1733         // pass
1734         return null;
1735     }
1736 
1737     @Override
stopService(Intent arg0)1738     public boolean stopService(Intent arg0) {
1739         // pass
1740         return false;
1741     }
1742 
1743     @Override
startServiceAsUser(Intent arg0, UserHandle arg1)1744     public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
1745         // pass
1746         return null;
1747     }
1748 
1749     @Override
stopServiceAsUser(Intent arg0, UserHandle arg1)1750     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
1751         // pass
1752         return false;
1753     }
1754 
1755     @Override
unbindService(ServiceConnection arg0)1756     public void unbindService(ServiceConnection arg0) {
1757         // pass
1758 
1759     }
1760 
1761     @Override
unregisterReceiver(BroadcastReceiver arg0)1762     public void unregisterReceiver(BroadcastReceiver arg0) {
1763         // pass
1764 
1765     }
1766 
1767     @Override
getApplicationContext()1768     public Context getApplicationContext() {
1769         return this;
1770     }
1771 
1772     @Override
startActivities(Intent[] arg0)1773     public void startActivities(Intent[] arg0) {
1774         // pass
1775 
1776     }
1777 
1778     @Override
startActivities(Intent[] arg0, Bundle arg1)1779     public void startActivities(Intent[] arg0, Bundle arg1) {
1780         // pass
1781 
1782     }
1783 
1784     @Override
isRestricted()1785     public boolean isRestricted() {
1786         return false;
1787     }
1788 
1789     @Override
getObbDir()1790     public File getObbDir() {
1791         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
1792         return null;
1793     }
1794 
1795     @Override
getDisplayAdjustments(int displayId)1796     public DisplayAdjustments getDisplayAdjustments(int displayId) {
1797         // pass
1798         return null;
1799     }
1800 
1801     @Override
getDisplay()1802     public Display getDisplay() {
1803         // pass
1804         return null;
1805     }
1806 
1807     @Override
getUserId()1808     public int getUserId() {
1809         return 0; // not used
1810     }
1811 
1812     @Override
getExternalFilesDirs(String type)1813     public File[] getExternalFilesDirs(String type) {
1814         // pass
1815         return new File[0];
1816     }
1817 
1818     @Override
getObbDirs()1819     public File[] getObbDirs() {
1820         // pass
1821         return new File[0];
1822     }
1823 
1824     @Override
getExternalCacheDirs()1825     public File[] getExternalCacheDirs() {
1826         // pass
1827         return new File[0];
1828     }
1829 
1830     @Override
getExternalMediaDirs()1831     public File[] getExternalMediaDirs() {
1832         // pass
1833         return new File[0];
1834     }
1835 
setScrollYPos(@onNull View view, int scrollPos)1836     public void setScrollYPos(@NonNull View view, int scrollPos) {
1837         mScrollYPos.put(view, scrollPos);
1838     }
1839 
getScrollYPos(@onNull View view)1840     public int getScrollYPos(@NonNull View view) {
1841         Integer pos = mScrollYPos.get(view);
1842         return pos != null ? pos : 0;
1843     }
1844 
setScrollXPos(@onNull View view, int scrollPos)1845     public void setScrollXPos(@NonNull View view, int scrollPos) {
1846         mScrollXPos.put(view, scrollPos);
1847     }
1848 
getScrollXPos(@onNull View view)1849     public int getScrollXPos(@NonNull View view) {
1850         Integer pos = mScrollXPos.get(view);
1851         return pos != null ? pos : 0;
1852     }
1853 
1854     @Override
createDeviceProtectedStorageContext()1855     public Context createDeviceProtectedStorageContext() {
1856         // pass
1857         return null;
1858     }
1859 
1860     @Override
createCredentialProtectedStorageContext()1861     public Context createCredentialProtectedStorageContext() {
1862         // pass
1863         return null;
1864     }
1865 
1866     @Override
isDeviceProtectedStorage()1867     public boolean isDeviceProtectedStorage() {
1868         return false;
1869     }
1870 
1871     @Override
isCredentialProtectedStorage()1872     public boolean isCredentialProtectedStorage() {
1873         return false;
1874     }
1875 
1876     /**
1877      * The cached value depends on
1878      * <ol>
1879      * <li>{@code int[]}: the attributes for which TypedArray is created </li>
1880      * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
1881      * creation of the TypedArray</li>
1882      * <li>{@code Integer}: the default style used at the time of creation</li>
1883      * </ol>
1884      *
1885      * The class is created by using nested maps resolving one dependency at a time.
1886      * <p/>
1887      * The final value of the nested maps is a pair of the typed array and a map of properties
1888      * that should be added to {@link #mDefaultPropMaps}, if needed.
1889      */
1890     private static class TypedArrayCache {
1891 
1892         private Map<int[],
1893                 Map<List<StyleResourceValue>,
1894                         Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
1895 
TypedArrayCache()1896         public TypedArrayCache() {
1897             mCache = new IdentityHashMap<>();
1898         }
1899 
get(int[] attrs, List<StyleResourceValue> themes, int resId)1900         public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
1901                 List<StyleResourceValue> themes, int resId) {
1902             Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
1903                     cacheFromThemes = mCache.get(attrs);
1904             if (cacheFromThemes != null) {
1905                 Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
1906                         cacheFromThemes.get(themes);
1907                 if (cacheFromResId != null) {
1908                     return cacheFromResId.get(resId);
1909                 }
1910             }
1911             return null;
1912         }
1913 
put(int[] attrs, List<StyleResourceValue> themes, int resId, Pair<BridgeTypedArray, PropertiesMap> value)1914         public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
1915                 Pair<BridgeTypedArray, PropertiesMap> value) {
1916             Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
1917                     cacheFromThemes = mCache.get(attrs);
1918             if (cacheFromThemes == null) {
1919                 cacheFromThemes = new HashMap<>();
1920                 mCache.put(attrs, cacheFromThemes);
1921             }
1922             Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
1923                     cacheFromThemes.get(themes);
1924             if (cacheFromResId == null) {
1925                 cacheFromResId = new HashMap<>();
1926                 cacheFromThemes.put(themes, cacheFromResId);
1927             }
1928             cacheFromResId.put(resId, value);
1929         }
1930 
1931     }
1932 }
1933