Home | History | Annotate | Download | only in android
      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      */
    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      */
    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      */
    239     public void disposeResources() {
    240         Resources_Delegate.disposeSystem();
    241     }
    242 
    243     public void setBridgeInflater(BridgeInflater inflater) {
    244         mBridgeInflater = inflater;
    245     }
    246 
    247     public void addViewKey(View view, Object viewKey) {
    248         mViewKeyMap.put(view, viewKey);
    249     }
    250 
    251     public Object getViewKey(View view) {
    252         return mViewKeyMap.get(view);
    253     }
    254 
    255     public void addCookie(Object o, Object cookie) {
    256         mViewKeyHelpMap.put(o, cookie);
    257     }
    258 
    259     public Object getCookie(Object o) {
    260         return mViewKeyHelpMap.get(o);
    261     }
    262 
    263     public Object getProjectKey() {
    264         return mProjectKey;
    265     }
    266 
    267     public DisplayMetrics getMetrics() {
    268         return mMetrics;
    269     }
    270 
    271     public LayoutlibCallback getLayoutlibCallback() {
    272         return mLayoutlibCallback;
    273     }
    274 
    275     public RenderResources getRenderResources() {
    276         return mRenderResources;
    277     }
    278 
    279     public Map<Object, PropertiesMap> getDefaultProperties() {
    280         return mDefaultPropMaps;
    281     }
    282 
    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      */
    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      */
    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      */
    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      */
    320     public BridgeXmlBlockParser getPreviousParser() {
    321         if (mParserStack.size() < 2) {
    322             return null;
    323         }
    324         return mParserStack.get(mParserStack.size() - 2);
    325     }
    326 
    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 
    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 
    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")
    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
    496     public Resources getResources() {
    497         return mSystemResources;
    498     }
    499 
    500     @Override
    501     public Theme getTheme() {
    502         return mTheme;
    503     }
    504 
    505     @Override
    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
    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
    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
    603     public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
    604         return obtainStyledAttributes(0, attrs);
    605     }
    606 
    607     @Override
    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
    659     public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
    660         return obtainStyledAttributes(set, attrs, 0, 0);
    661     }
    662 
    663     @Override
    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
    903     public Looper getMainLooper() {
    904         return Looper.myLooper();
    905     }
    906 
    907 
    908     @Override
    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
    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      */
    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      */
    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      */
   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 
   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 
   1048     private StyleResourceValue getStyleByDynamicId(int i) {
   1049         if (mDynamicIdToStyleMap != null) {
   1050             return mDynamicIdToStyleMap.get(i);
   1051         }
   1052 
   1053         return null;
   1054     }
   1055 
   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 
   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 
   1081     public static Context getBaseContext(Context context) {
   1082         while (context instanceof ContextWrapper) {
   1083             context = ((ContextWrapper) context).getBaseContext();
   1084         }
   1085         return context;
   1086     }
   1087 
   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
   1151     public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
   1152         // pass
   1153         return false;
   1154     }
   1155 
   1156     @Override
   1157     public int checkCallingOrSelfPermission(String arg0) {
   1158         // pass
   1159         return 0;
   1160     }
   1161 
   1162     @Override
   1163     public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
   1164         // pass
   1165         return 0;
   1166     }
   1167 
   1168     @Override
   1169     public int checkCallingPermission(String arg0) {
   1170         // pass
   1171         return 0;
   1172     }
   1173 
   1174     @Override
   1175     public int checkCallingUriPermission(Uri arg0, int arg1) {
   1176         // pass
   1177         return 0;
   1178     }
   1179 
   1180     @Override
   1181     public int checkPermission(String arg0, int arg1, int arg2) {
   1182         // pass
   1183         return 0;
   1184     }
   1185 
   1186     @Override
   1187     public int checkSelfPermission(String arg0) {
   1188         // pass
   1189         return 0;
   1190     }
   1191 
   1192     @Override
   1193     public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
   1194         // pass
   1195         return 0;
   1196     }
   1197 
   1198     @Override
   1199     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
   1200         // pass
   1201         return 0;
   1202     }
   1203 
   1204     @Override
   1205     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) {
   1206         // pass
   1207         return 0;
   1208     }
   1209 
   1210     @Override
   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
   1218     public void clearWallpaper() {
   1219         // pass
   1220 
   1221     }
   1222 
   1223     @Override
   1224     public Context createPackageContext(String arg0, int arg1) {
   1225         // pass
   1226         return null;
   1227     }
   1228 
   1229     @Override
   1230     public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
   1231         // pass
   1232         return null;
   1233     }
   1234 
   1235     @Override
   1236     public Context createConfigurationContext(Configuration overrideConfiguration) {
   1237         // pass
   1238         return null;
   1239     }
   1240 
   1241     @Override
   1242     public Context createDisplayContext(Display display) {
   1243         // pass
   1244         return null;
   1245     }
   1246 
   1247     @Override
   1248     public String[] databaseList() {
   1249         // pass
   1250         return null;
   1251     }
   1252 
   1253     @Override
   1254     public Context createApplicationContext(ApplicationInfo application, int flags)
   1255             throws PackageManager.NameNotFoundException {
   1256         return null;
   1257     }
   1258 
   1259     @Override
   1260     public boolean moveDatabaseFrom(Context sourceContext, String name) {
   1261         // pass
   1262         return false;
   1263     }
   1264 
   1265     @Override
   1266     public boolean deleteDatabase(String arg0) {
   1267         // pass
   1268         return false;
   1269     }
   1270 
   1271     @Override
   1272     public boolean deleteFile(String arg0) {
   1273         // pass
   1274         return false;
   1275     }
   1276 
   1277     @Override
   1278     public void enforceCallingOrSelfPermission(String arg0, String arg1) {
   1279         // pass
   1280 
   1281     }
   1282 
   1283     @Override
   1284     public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
   1285             String arg2) {
   1286         // pass
   1287 
   1288     }
   1289 
   1290     @Override
   1291     public void enforceCallingPermission(String arg0, String arg1) {
   1292         // pass
   1293 
   1294     }
   1295 
   1296     @Override
   1297     public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
   1298         // pass
   1299 
   1300     }
   1301 
   1302     @Override
   1303     public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
   1304         // pass
   1305 
   1306     }
   1307 
   1308     @Override
   1309     public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
   1310             String arg4) {
   1311         // pass
   1312 
   1313     }
   1314 
   1315     @Override
   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
   1323     public String[] fileList() {
   1324         // pass
   1325         return null;
   1326     }
   1327 
   1328     @Override
   1329     public BridgeAssetManager getAssets() {
   1330         return mAssets;
   1331     }
   1332 
   1333     @Override
   1334     public File getCacheDir() {
   1335         // pass
   1336         return null;
   1337     }
   1338 
   1339     @Override
   1340     public File getCodeCacheDir() {
   1341         // pass
   1342         return null;
   1343     }
   1344 
   1345     @Override
   1346     public File getExternalCacheDir() {
   1347         // pass
   1348         return null;
   1349     }
   1350 
   1351     @Override
   1352     public ContentResolver getContentResolver() {
   1353         if (mContentResolver == null) {
   1354             mContentResolver = new BridgeContentResolver(this);
   1355         }
   1356         return mContentResolver;
   1357     }
   1358 
   1359     @Override
   1360     public File getDatabasePath(String arg0) {
   1361         // pass
   1362         return null;
   1363     }
   1364 
   1365     @Override
   1366     public File getDir(String arg0, int arg1) {
   1367         // pass
   1368         return null;
   1369     }
   1370 
   1371     @Override
   1372     public File getFileStreamPath(String arg0) {
   1373         // pass
   1374         return null;
   1375     }
   1376 
   1377     @Override
   1378     public File getSharedPreferencesPath(String name) {
   1379         // pass
   1380         return null;
   1381     }
   1382 
   1383     @Override
   1384     public File getDataDir() {
   1385         // pass
   1386         return null;
   1387     }
   1388 
   1389     @Override
   1390     public File getFilesDir() {
   1391         // pass
   1392         return null;
   1393     }
   1394 
   1395     @Override
   1396     public File getNoBackupFilesDir() {
   1397         // pass
   1398         return null;
   1399     }
   1400 
   1401     @Override
   1402     public File getExternalFilesDir(String type) {
   1403         // pass
   1404         return null;
   1405     }
   1406 
   1407     @Override
   1408     public String getPackageCodePath() {
   1409         // pass
   1410         return null;
   1411     }
   1412 
   1413     @Override
   1414     public String getBasePackageName() {
   1415         // pass
   1416         return null;
   1417     }
   1418 
   1419     @Override
   1420     public String getOpPackageName() {
   1421         // pass
   1422         return null;
   1423     }
   1424 
   1425     @Override
   1426     public ApplicationInfo getApplicationInfo() {
   1427         return mApplicationInfo;
   1428     }
   1429 
   1430     @Override
   1431     public String getPackageResourcePath() {
   1432         // pass
   1433         return null;
   1434     }
   1435 
   1436     @Override
   1437     public SharedPreferences getSharedPreferences(String arg0, int arg1) {
   1438         if (mSharedPreferences == null) {
   1439             mSharedPreferences = new BridgeSharedPreferences();
   1440         }
   1441         return mSharedPreferences;
   1442     }
   1443 
   1444     @Override
   1445     public SharedPreferences getSharedPreferences(File arg0, int arg1) {
   1446         if (mSharedPreferences == null) {
   1447             mSharedPreferences = new BridgeSharedPreferences();
   1448         }
   1449         return mSharedPreferences;
   1450     }
   1451 
   1452     @Override
   1453     public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
   1454         // pass
   1455         return false;
   1456     }
   1457 
   1458     @Override
   1459     public boolean deleteSharedPreferences(String name) {
   1460         // pass
   1461         return false;
   1462     }
   1463 
   1464     @Override
   1465     public Drawable getWallpaper() {
   1466         // pass
   1467         return null;
   1468     }
   1469 
   1470     @Override
   1471     public int getWallpaperDesiredMinimumWidth() {
   1472         return -1;
   1473     }
   1474 
   1475     @Override
   1476     public int getWallpaperDesiredMinimumHeight() {
   1477         return -1;
   1478     }
   1479 
   1480     @Override
   1481     public void grantUriPermission(String arg0, Uri arg1, int arg2) {
   1482         // pass
   1483 
   1484     }
   1485 
   1486     @Override
   1487     public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
   1488         // pass
   1489         return null;
   1490     }
   1491 
   1492     @Override
   1493     public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
   1494         // pass
   1495         return null;
   1496     }
   1497 
   1498     @Override
   1499     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
   1500         // pass
   1501         return null;
   1502     }
   1503 
   1504     @Override
   1505     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
   1506             CursorFactory arg2, DatabaseErrorHandler arg3) {
   1507         // pass
   1508         return null;
   1509     }
   1510 
   1511     @Override
   1512     public Drawable peekWallpaper() {
   1513         // pass
   1514         return null;
   1515     }
   1516 
   1517     @Override
   1518     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
   1519         // pass
   1520         return null;
   1521     }
   1522 
   1523     @Override
   1524     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
   1525             String arg2, Handler arg3) {
   1526         // pass
   1527         return null;
   1528     }
   1529 
   1530     @Override
   1531     public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
   1532             IntentFilter arg1, String arg2, Handler arg3) {
   1533         // pass
   1534         return null;
   1535     }
   1536 
   1537     @Override
   1538     public void removeStickyBroadcast(Intent arg0) {
   1539         // pass
   1540 
   1541     }
   1542 
   1543     @Override
   1544     public void revokeUriPermission(Uri arg0, int arg1) {
   1545         // pass
   1546 
   1547     }
   1548 
   1549     @Override
   1550     public void sendBroadcast(Intent arg0) {
   1551         // pass
   1552 
   1553     }
   1554 
   1555     @Override
   1556     public void sendBroadcast(Intent arg0, String arg1) {
   1557         // pass
   1558 
   1559     }
   1560 
   1561     @Override
   1562     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
   1563         // pass
   1564 
   1565     }
   1566 
   1567     @Override
   1568     public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) {
   1569         // pass
   1570 
   1571     }
   1572 
   1573     @Override
   1574     public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
   1575         // pass
   1576     }
   1577 
   1578     @Override
   1579     public void sendOrderedBroadcast(Intent arg0, String arg1) {
   1580         // pass
   1581 
   1582     }
   1583 
   1584     @Override
   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
   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
   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
   1608     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
   1609         // pass
   1610     }
   1611 
   1612     @Override
   1613     public void sendBroadcastAsUser(Intent intent, UserHandle user,
   1614             String receiverPermission) {
   1615         // pass
   1616     }
   1617 
   1618     public void sendBroadcastAsUser(Intent intent, UserHandle user,
   1619             String receiverPermission, int appOp) {
   1620         // pass
   1621     }
   1622 
   1623     @Override
   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
   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
   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
   1647     public void sendStickyBroadcast(Intent arg0) {
   1648         // pass
   1649 
   1650     }
   1651 
   1652     @Override
   1653     public void sendStickyOrderedBroadcast(Intent intent,
   1654             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
   1655            Bundle initialExtras) {
   1656         // pass
   1657     }
   1658 
   1659     @Override
   1660     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
   1661         // pass
   1662     }
   1663 
   1664     @Override
   1665     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
   1666         // pass
   1667     }
   1668 
   1669     @Override
   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
   1678     public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
   1679         // pass
   1680     }
   1681 
   1682     @Override
   1683     public void setTheme(int arg0) {
   1684         // pass
   1685 
   1686     }
   1687 
   1688     @Override
   1689     public void setWallpaper(Bitmap arg0) throws IOException {
   1690         // pass
   1691 
   1692     }
   1693 
   1694     @Override
   1695     public void setWallpaper(InputStream arg0) throws IOException {
   1696         // pass
   1697 
   1698     }
   1699 
   1700     @Override
   1701     public void startActivity(Intent arg0) {
   1702         // pass
   1703     }
   1704 
   1705     @Override
   1706     public void startActivity(Intent arg0, Bundle arg1) {
   1707         // pass
   1708     }
   1709 
   1710     @Override
   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
   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
   1725     public boolean startInstrumentation(ComponentName arg0, String arg1,
   1726             Bundle arg2) {
   1727         // pass
   1728         return false;
   1729     }
   1730 
   1731     @Override
   1732     public ComponentName startService(Intent arg0) {
   1733         // pass
   1734         return null;
   1735     }
   1736 
   1737     @Override
   1738     public boolean stopService(Intent arg0) {
   1739         // pass
   1740         return false;
   1741     }
   1742 
   1743     @Override
   1744     public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
   1745         // pass
   1746         return null;
   1747     }
   1748 
   1749     @Override
   1750     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
   1751         // pass
   1752         return false;
   1753     }
   1754 
   1755     @Override
   1756     public void unbindService(ServiceConnection arg0) {
   1757         // pass
   1758 
   1759     }
   1760 
   1761     @Override
   1762     public void unregisterReceiver(BroadcastReceiver arg0) {
   1763         // pass
   1764 
   1765     }
   1766 
   1767     @Override
   1768     public Context getApplicationContext() {
   1769         return this;
   1770     }
   1771 
   1772     @Override
   1773     public void startActivities(Intent[] arg0) {
   1774         // pass
   1775 
   1776     }
   1777 
   1778     @Override
   1779     public void startActivities(Intent[] arg0, Bundle arg1) {
   1780         // pass
   1781 
   1782     }
   1783 
   1784     @Override
   1785     public boolean isRestricted() {
   1786         return false;
   1787     }
   1788 
   1789     @Override
   1790     public File getObbDir() {
   1791         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
   1792         return null;
   1793     }
   1794 
   1795     @Override
   1796     public DisplayAdjustments getDisplayAdjustments(int displayId) {
   1797         // pass
   1798         return null;
   1799     }
   1800 
   1801     @Override
   1802     public Display getDisplay() {
   1803         // pass
   1804         return null;
   1805     }
   1806 
   1807     @Override
   1808     public int getUserId() {
   1809         return 0; // not used
   1810     }
   1811 
   1812     @Override
   1813     public File[] getExternalFilesDirs(String type) {
   1814         // pass
   1815         return new File[0];
   1816     }
   1817 
   1818     @Override
   1819     public File[] getObbDirs() {
   1820         // pass
   1821         return new File[0];
   1822     }
   1823 
   1824     @Override
   1825     public File[] getExternalCacheDirs() {
   1826         // pass
   1827         return new File[0];
   1828     }
   1829 
   1830     @Override
   1831     public File[] getExternalMediaDirs() {
   1832         // pass
   1833         return new File[0];
   1834     }
   1835 
   1836     public void setScrollYPos(@NonNull View view, int scrollPos) {
   1837         mScrollYPos.put(view, scrollPos);
   1838     }
   1839 
   1840     public int getScrollYPos(@NonNull View view) {
   1841         Integer pos = mScrollYPos.get(view);
   1842         return pos != null ? pos : 0;
   1843     }
   1844 
   1845     public void setScrollXPos(@NonNull View view, int scrollPos) {
   1846         mScrollXPos.put(view, scrollPos);
   1847     }
   1848 
   1849     public int getScrollXPos(@NonNull View view) {
   1850         Integer pos = mScrollXPos.get(view);
   1851         return pos != null ? pos : 0;
   1852     }
   1853 
   1854     @Override
   1855     public Context createDeviceProtectedStorageContext() {
   1856         // pass
   1857         return null;
   1858     }
   1859 
   1860     @Override
   1861     public Context createCredentialProtectedStorageContext() {
   1862         // pass
   1863         return null;
   1864     }
   1865 
   1866     @Override
   1867     public boolean isDeviceProtectedStorage() {
   1868         return false;
   1869     }
   1870 
   1871     @Override
   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 
   1896         public TypedArrayCache() {
   1897             mCache = new IdentityHashMap<>();
   1898         }
   1899 
   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 
   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