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