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.ide.common.rendering.api.ILayoutPullParser;
     20 import com.android.ide.common.rendering.api.IProjectCallback;
     21 import com.android.ide.common.rendering.api.LayoutLog;
     22 import com.android.ide.common.rendering.api.RenderResources;
     23 import com.android.ide.common.rendering.api.ResourceReference;
     24 import com.android.ide.common.rendering.api.ResourceValue;
     25 import com.android.ide.common.rendering.api.StyleResourceValue;
     26 import com.android.layoutlib.bridge.Bridge;
     27 import com.android.layoutlib.bridge.BridgeConstants;
     28 import com.android.layoutlib.bridge.android.view.WindowManagerImpl;
     29 import com.android.layoutlib.bridge.impl.ParserFactory;
     30 import com.android.layoutlib.bridge.impl.Stack;
     31 import com.android.resources.ResourceType;
     32 import com.android.util.Pair;
     33 
     34 import org.xmlpull.v1.XmlPullParser;
     35 import org.xmlpull.v1.XmlPullParserException;
     36 
     37 import android.content.BroadcastReceiver;
     38 import android.content.ComponentName;
     39 import android.content.ContentResolver;
     40 import android.content.Context;
     41 import android.content.Intent;
     42 import android.content.IntentFilter;
     43 import android.content.IntentSender;
     44 import android.content.ServiceConnection;
     45 import android.content.SharedPreferences;
     46 import android.content.pm.ApplicationInfo;
     47 import android.content.pm.PackageManager;
     48 import android.content.res.AssetManager;
     49 import android.content.res.BridgeResources;
     50 import android.content.res.BridgeTypedArray;
     51 import android.content.res.Configuration;
     52 import android.content.res.Resources;
     53 import android.content.res.Resources.Theme;
     54 import android.content.res.TypedArray;
     55 import android.database.DatabaseErrorHandler;
     56 import android.database.sqlite.SQLiteDatabase;
     57 import android.database.sqlite.SQLiteDatabase.CursorFactory;
     58 import android.graphics.Bitmap;
     59 import android.graphics.drawable.Drawable;
     60 import android.net.Uri;
     61 import android.os.Bundle;
     62 import android.os.Handler;
     63 import android.os.Looper;
     64 import android.os.PowerManager;
     65 import android.os.UserHandle;
     66 import android.util.AttributeSet;
     67 import android.util.DisplayMetrics;
     68 import android.util.TypedValue;
     69 import android.view.BridgeInflater;
     70 import android.view.CompatibilityInfoHolder;
     71 import android.view.Display;
     72 import android.view.View;
     73 import android.view.ViewGroup;
     74 import android.view.WindowManager;
     75 import android.view.textservice.TextServicesManager;
     76 
     77 import java.io.File;
     78 import java.io.FileInputStream;
     79 import java.io.FileNotFoundException;
     80 import java.io.FileOutputStream;
     81 import java.io.IOException;
     82 import java.io.InputStream;
     83 import java.util.ArrayList;
     84 import java.util.HashMap;
     85 import java.util.IdentityHashMap;
     86 import java.util.List;
     87 import java.util.Map;
     88 
     89 /**
     90  * Custom implementation of Context/Activity to handle non compiled resources.
     91  */
     92 public final class BridgeContext extends Context {
     93 
     94     private Resources mSystemResources;
     95     private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
     96     private final Object mProjectKey;
     97     private final DisplayMetrics mMetrics;
     98     private final RenderResources mRenderResources;
     99     private final Configuration mConfig;
    100     private final ApplicationInfo mApplicationInfo;
    101     private final IProjectCallback mProjectCallback;
    102     private final WindowManager mWindowManager;
    103 
    104     private Resources.Theme mTheme;
    105 
    106     private final Map<Object, Map<String, String>> mDefaultPropMaps =
    107         new IdentityHashMap<Object, Map<String,String>>();
    108 
    109     // maps for dynamically generated id representing style objects (StyleResourceValue)
    110     private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
    111     private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
    112     private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style
    113 
    114     // cache for TypedArray generated from IStyleResourceValue object
    115     private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
    116     private BridgeInflater mBridgeInflater;
    117 
    118     private BridgeContentResolver mContentResolver;
    119 
    120     private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
    121 
    122     /**
    123      * @param projectKey An Object identifying the project. This is used for the cache mechanism.
    124      * @param metrics the {@link DisplayMetrics}.
    125      * @param renderResources the configured resources (both framework and projects) for this
    126      * render.
    127      * @param projectCallback
    128      * @param config the Configuration object for this render.
    129      * @param targetSdkVersion the targetSdkVersion of the application.
    130      */
    131     public BridgeContext(Object projectKey, DisplayMetrics metrics,
    132             RenderResources renderResources,
    133             IProjectCallback projectCallback,
    134             Configuration config,
    135             int targetSdkVersion) {
    136         mProjectKey = projectKey;
    137         mMetrics = metrics;
    138         mProjectCallback = projectCallback;
    139 
    140         mRenderResources = renderResources;
    141         mConfig = config;
    142 
    143         mApplicationInfo = new ApplicationInfo();
    144         mApplicationInfo.targetSdkVersion = targetSdkVersion;
    145 
    146         mWindowManager = new WindowManagerImpl(mMetrics);
    147     }
    148 
    149     /**
    150      * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its
    151      * {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}.
    152      *
    153      * @see #disposeResources()
    154      */
    155     public void initResources() {
    156         AssetManager assetManager = AssetManager.getSystem();
    157 
    158         mSystemResources = BridgeResources.initSystem(
    159                 this,
    160                 assetManager,
    161                 mMetrics,
    162                 mConfig,
    163                 mProjectCallback);
    164         mTheme = mSystemResources.newTheme();
    165     }
    166 
    167     /**
    168      * Disposes the {@link Resources} singleton.
    169      */
    170     public void disposeResources() {
    171         BridgeResources.disposeSystem();
    172     }
    173 
    174     public void setBridgeInflater(BridgeInflater inflater) {
    175         mBridgeInflater = inflater;
    176     }
    177 
    178     public void addViewKey(View view, Object viewKey) {
    179         mViewKeyMap.put(view, viewKey);
    180     }
    181 
    182     public Object getViewKey(View view) {
    183         return mViewKeyMap.get(view);
    184     }
    185 
    186     public Object getProjectKey() {
    187         return mProjectKey;
    188     }
    189 
    190     public DisplayMetrics getMetrics() {
    191         return mMetrics;
    192     }
    193 
    194     public IProjectCallback getProjectCallback() {
    195         return mProjectCallback;
    196     }
    197 
    198     public RenderResources getRenderResources() {
    199         return mRenderResources;
    200     }
    201 
    202     public Map<String, String> getDefaultPropMap(Object key) {
    203         return mDefaultPropMaps.get(key);
    204     }
    205 
    206     public Configuration getConfiguration() {
    207         return mConfig;
    208     }
    209 
    210     /**
    211      * Adds a parser to the stack.
    212      * @param parser the parser to add.
    213      */
    214     public void pushParser(BridgeXmlBlockParser parser) {
    215         if (ParserFactory.LOG_PARSER) {
    216             System.out.println("PUSH " + parser.getParser().toString());
    217         }
    218         mParserStack.push(parser);
    219     }
    220 
    221     /**
    222      * Removes the parser at the top of the stack
    223      */
    224     public void popParser() {
    225         BridgeXmlBlockParser parser = mParserStack.pop();
    226         if (ParserFactory.LOG_PARSER) {
    227             System.out.println("POPD " + parser.getParser().toString());
    228         }
    229     }
    230 
    231     /**
    232      * Returns the current parser at the top the of the stack.
    233      * @return a parser or null.
    234      */
    235     public BridgeXmlBlockParser getCurrentParser() {
    236         return mParserStack.peek();
    237     }
    238 
    239     /**
    240      * Returns the previous parser.
    241      * @return a parser or null if there isn't any previous parser
    242      */
    243     public BridgeXmlBlockParser getPreviousParser() {
    244         if (mParserStack.size() < 2) {
    245             return null;
    246         }
    247         return mParserStack.get(mParserStack.size() - 2);
    248     }
    249 
    250     public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
    251         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
    252         boolean isFrameworkRes = true;
    253         if (resourceInfo == null) {
    254             resourceInfo = mProjectCallback.resolveResourceId(resid);
    255             isFrameworkRes = false;
    256         }
    257 
    258         if (resourceInfo == null) {
    259             return false;
    260         }
    261 
    262         ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(),
    263                 isFrameworkRes);
    264         if (resolveRefs) {
    265             value = mRenderResources.resolveResValue(value);
    266         }
    267 
    268         // check if this is a style resource
    269         if (value instanceof StyleResourceValue) {
    270             // get the id that will represent this style.
    271             outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value);
    272             return true;
    273         }
    274 
    275 
    276         int a;
    277         // if this is a framework value.
    278         if (value.isFramework()) {
    279             // look for idName in the android R classes.
    280             // use 0 a default res value as it's not a valid id value.
    281             a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
    282         } else {
    283             // look for idName in the project R class.
    284             // use 0 a default res value as it's not a valid id value.
    285             a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
    286         }
    287 
    288         if (a != 0) {
    289             outValue.resourceId = a;
    290             return true;
    291         }
    292 
    293         return false;
    294     }
    295 
    296 
    297     public ResourceReference resolveId(int id) {
    298         // first get the String related to this id in the framework
    299         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
    300 
    301         if (resourceInfo != null) {
    302             return new ResourceReference(resourceInfo.getSecond(), true);
    303         }
    304 
    305         // didn't find a match in the framework? look in the project.
    306         if (mProjectCallback != null) {
    307             resourceInfo = mProjectCallback.resolveResourceId(id);
    308 
    309             if (resourceInfo != null) {
    310                 return new ResourceReference(resourceInfo.getSecond(), false);
    311             }
    312         }
    313 
    314         return null;
    315     }
    316 
    317     public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent,
    318             boolean attachToRoot, boolean skipCallbackParser) {
    319         boolean isPlatformLayout = resource.isFramework();
    320 
    321         if (isPlatformLayout == false && skipCallbackParser == false) {
    322             // check if the project callback can provide us with a custom parser.
    323             ILayoutPullParser parser = getParser(resource);
    324 
    325             if (parser != null) {
    326                 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
    327                         this, resource.isFramework());
    328                 try {
    329                     pushParser(blockParser);
    330                     return Pair.of(
    331                             mBridgeInflater.inflate(blockParser, parent, attachToRoot),
    332                             true);
    333                 } finally {
    334                     popParser();
    335                 }
    336             }
    337         }
    338 
    339         ResourceValue resValue;
    340         if (resource instanceof ResourceValue) {
    341             resValue = (ResourceValue) resource;
    342         } else {
    343             if (isPlatformLayout) {
    344                 resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT,
    345                         resource.getName());
    346             } else {
    347                 resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT,
    348                         resource.getName());
    349             }
    350         }
    351 
    352         if (resValue != null) {
    353 
    354             File xml = new File(resValue.getValue());
    355             if (xml.isFile()) {
    356                 // we need to create a pull parser around the layout XML file, and then
    357                 // give that to our XmlBlockParser
    358                 try {
    359                     XmlPullParser parser = ParserFactory.create(xml);
    360 
    361                     // set the resource ref to have correct view cookies
    362                     mBridgeInflater.setResourceReference(resource);
    363 
    364                     BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
    365                             this, resource.isFramework());
    366                     try {
    367                         pushParser(blockParser);
    368                         return Pair.of(
    369                                 mBridgeInflater.inflate(blockParser, parent, attachToRoot),
    370                                 false);
    371                     } finally {
    372                         popParser();
    373                     }
    374                 } catch (XmlPullParserException e) {
    375                     Bridge.getLog().error(LayoutLog.TAG_BROKEN,
    376                             "Failed to configure parser for " + xml, e, null /*data*/);
    377                     // we'll return null below.
    378                 } catch (FileNotFoundException e) {
    379                     // this shouldn't happen since we check above.
    380                 } finally {
    381                     mBridgeInflater.setResourceReference(null);
    382                 }
    383             } else {
    384                 Bridge.getLog().error(LayoutLog.TAG_BROKEN,
    385                         String.format("File %s is missing!", xml), null);
    386             }
    387         } else {
    388             Bridge.getLog().error(LayoutLog.TAG_BROKEN,
    389                     String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "",
    390                             resource.getName()), null);
    391         }
    392 
    393         return Pair.of(null, false);
    394     }
    395 
    396     @SuppressWarnings("deprecation")
    397     private ILayoutPullParser getParser(ResourceReference resource) {
    398         ILayoutPullParser parser;
    399         if (resource instanceof ResourceValue) {
    400             parser = mProjectCallback.getParser((ResourceValue) resource);
    401         } else {
    402             parser = mProjectCallback.getParser(resource.getName());
    403         }
    404         return parser;
    405     }
    406 
    407     // ------------ Context methods
    408 
    409     @Override
    410     public Resources getResources() {
    411         return mSystemResources;
    412     }
    413 
    414     @Override
    415     public Theme getTheme() {
    416         return mTheme;
    417     }
    418 
    419     @Override
    420     public ClassLoader getClassLoader() {
    421         return this.getClass().getClassLoader();
    422     }
    423 
    424     @Override
    425     public Object getSystemService(String service) {
    426         if (LAYOUT_INFLATER_SERVICE.equals(service)) {
    427             return mBridgeInflater;
    428         }
    429 
    430         if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) {
    431             // we need to return a valid service to avoid NPE
    432             return TextServicesManager.getInstance();
    433         }
    434 
    435         if (WINDOW_SERVICE.equals(service)) {
    436             return mWindowManager;
    437         }
    438 
    439         // needed by SearchView
    440         if (INPUT_METHOD_SERVICE.equals(service)) {
    441             return null;
    442         }
    443 
    444         if (POWER_SERVICE.equals(service)) {
    445             return new PowerManager(this, new BridgePowerManager(), new Handler());
    446         }
    447 
    448         throw new UnsupportedOperationException("Unsupported Service: " + service);
    449     }
    450 
    451 
    452     @Override
    453     public final TypedArray obtainStyledAttributes(int[] attrs) {
    454         return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs);
    455     }
    456 
    457     @Override
    458     public final TypedArray obtainStyledAttributes(int resid, int[] attrs)
    459             throws Resources.NotFoundException {
    460         // get the StyleResourceValue based on the resId;
    461         StyleResourceValue style = getStyleByDynamicId(resid);
    462 
    463         if (style == null) {
    464             throw new Resources.NotFoundException();
    465         }
    466 
    467         if (mTypedArrayCache == null) {
    468             mTypedArrayCache = new HashMap<int[], Map<Integer,TypedArray>>();
    469 
    470             Map<Integer, TypedArray> map = new HashMap<Integer, TypedArray>();
    471             mTypedArrayCache.put(attrs, map);
    472 
    473             BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs);
    474             map.put(resid, ta);
    475 
    476             return ta;
    477         }
    478 
    479         // get the 2nd map
    480         Map<Integer, TypedArray> map = mTypedArrayCache.get(attrs);
    481         if (map == null) {
    482             map = new HashMap<Integer, TypedArray>();
    483             mTypedArrayCache.put(attrs, map);
    484         }
    485 
    486         // get the array from the 2nd map
    487         TypedArray ta = map.get(resid);
    488 
    489         if (ta == null) {
    490             ta = createStyleBasedTypedArray(style, attrs);
    491             map.put(resid, ta);
    492         }
    493 
    494         return ta;
    495     }
    496 
    497     @Override
    498     public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
    499         return obtainStyledAttributes(set, attrs, 0, 0);
    500     }
    501 
    502     @Override
    503     public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
    504             int defStyleAttr, int defStyleRes) {
    505 
    506         Map<String, String> defaultPropMap = null;
    507         boolean isPlatformFile = true;
    508 
    509         // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
    510         if (set instanceof BridgeXmlBlockParser) {
    511             BridgeXmlBlockParser parser = null;
    512             parser = (BridgeXmlBlockParser)set;
    513 
    514             isPlatformFile = parser.isPlatformFile();
    515 
    516             Object key = parser.getViewCookie();
    517             if (key != null) {
    518                 defaultPropMap = mDefaultPropMaps.get(key);
    519                 if (defaultPropMap == null) {
    520                     defaultPropMap = new HashMap<String, String>();
    521                     mDefaultPropMaps.put(key, defaultPropMap);
    522                 }
    523             }
    524 
    525         } else if (set instanceof BridgeLayoutParamsMapAttributes) {
    526             // this is only for temp layout params generated dynamically, so this is never
    527             // platform content.
    528             isPlatformFile = false;
    529         } else if (set != null) { // null parser is ok
    530             // really this should not be happening since its instantiated in Bridge
    531             Bridge.getLog().error(LayoutLog.TAG_BROKEN,
    532                     "Parser is not a BridgeXmlBlockParser!", null /*data*/);
    533             return null;
    534         }
    535 
    536         List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
    537 
    538         BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
    539                 isPlatformFile);
    540 
    541         // look for a custom style.
    542         String customStyle = null;
    543         if (set != null) {
    544             customStyle = set.getAttributeValue(null /* namespace*/, "style");
    545         }
    546 
    547         StyleResourceValue customStyleValues = null;
    548         if (customStyle != null) {
    549             ResourceValue item = mRenderResources.findResValue(customStyle,
    550                     false /*forceFrameworkOnly*/);
    551 
    552             // resolve it in case it links to something else
    553             item = mRenderResources.resolveResValue(item);
    554 
    555             if (item instanceof StyleResourceValue) {
    556                 customStyleValues = (StyleResourceValue)item;
    557             }
    558         }
    559 
    560         // resolve the defStyleAttr value into a IStyleResourceValue
    561         StyleResourceValue defStyleValues = null;
    562 
    563         if (defStyleAttr != 0) {
    564             // get the name from the int.
    565             Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
    566 
    567             if (defaultPropMap != null) {
    568                 String defStyleName = defStyleAttribute.getFirst();
    569                 if (defStyleAttribute.getSecond()) {
    570                     defStyleName = "android:" + defStyleName;
    571                 }
    572                 defaultPropMap.put("style", defStyleName);
    573             }
    574 
    575             // look for the style in the current theme, and its parent:
    576             ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(),
    577                     defStyleAttribute.getSecond());
    578 
    579             if (item != null) {
    580                 // item is a reference to a style entry. Search for it.
    581                 item = mRenderResources.findResValue(item.getValue(),
    582                         false /*forceFrameworkOnly*/);
    583 
    584                 if (item instanceof StyleResourceValue) {
    585                     defStyleValues = (StyleResourceValue)item;
    586                 }
    587             } else {
    588                 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
    589                         String.format(
    590                                 "Failed to find style '%s' in current theme",
    591                                 defStyleAttribute.getFirst()),
    592                         null /*data*/);
    593             }
    594         } else if (defStyleRes != 0) {
    595             boolean isFrameworkRes = true;
    596             Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
    597             if (value == null) {
    598                 value = mProjectCallback.resolveResourceId(defStyleRes);
    599                 isFrameworkRes = false;
    600             }
    601 
    602             if (value != null) {
    603                 if (value.getFirst() == ResourceType.STYLE) {
    604                     // look for the style in the current theme, and its parent:
    605                     ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(),
    606                             isFrameworkRes);
    607                     if (item != null) {
    608                         if (item instanceof StyleResourceValue) {
    609                             if (defaultPropMap != null) {
    610                                 defaultPropMap.put("style", item.getName());
    611                             }
    612 
    613                             defStyleValues = (StyleResourceValue)item;
    614                         }
    615                     } else {
    616                         Bridge.getLog().error(null,
    617                                 String.format(
    618                                         "Style with id 0x%x (resolved to '%s') does not exist.",
    619                                         defStyleRes, value.getSecond()),
    620                                 null /*data*/);
    621                     }
    622                 } else {
    623                     Bridge.getLog().error(null,
    624                             String.format(
    625                                     "Resouce id 0x%x is not of type STYLE (instead %s)",
    626                                     defStyleRes, value.getFirst().toString()),
    627                             null /*data*/);
    628                 }
    629             } else {
    630                 Bridge.getLog().error(null,
    631                         String.format(
    632                                 "Failed to find style with id 0x%x in current theme",
    633                                 defStyleRes),
    634                         null /*data*/);
    635             }
    636         }
    637 
    638         String appNamespace = mProjectCallback.getNamespace();
    639 
    640         if (attributeList != null) {
    641             for (int index = 0 ; index < attributeList.size() ; index++) {
    642                 Pair<String, Boolean> attribute = attributeList.get(index);
    643 
    644                 if (attribute == null) {
    645                     continue;
    646                 }
    647 
    648                 String attrName = attribute.getFirst();
    649                 boolean frameworkAttr = attribute.getSecond().booleanValue();
    650                 String value = null;
    651                 if (set != null) {
    652                     value = set.getAttributeValue(
    653                             frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace,
    654                                     attrName);
    655 
    656                     // if this is an app attribute, and the first get fails, try with the
    657                     // new res-auto namespace as well
    658                     if (frameworkAttr == false && value == null) {
    659                         value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
    660                     }
    661                 }
    662 
    663                 // if there's no direct value for this attribute in the XML, we look for default
    664                 // values in the widget defStyle, and then in the theme.
    665                 if (value == null) {
    666                     ResourceValue resValue = null;
    667 
    668                     // look for the value in the custom style first (and its parent if needed)
    669                     if (customStyleValues != null) {
    670                         resValue = mRenderResources.findItemInStyle(customStyleValues,
    671                                 attrName, frameworkAttr);
    672                     }
    673 
    674                     // then look for the value in the default Style (and its parent if needed)
    675                     if (resValue == null && defStyleValues != null) {
    676                         resValue = mRenderResources.findItemInStyle(defStyleValues,
    677                                 attrName, frameworkAttr);
    678                     }
    679 
    680                     // if the item is not present in the defStyle, we look in the main theme (and
    681                     // its parent themes)
    682                     if (resValue == null) {
    683                         resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
    684                     }
    685 
    686                     // if we found a value, we make sure this doesn't reference another value.
    687                     // So we resolve it.
    688                     if (resValue != null) {
    689                         // put the first default value, before the resolution.
    690                         if (defaultPropMap != null) {
    691                             defaultPropMap.put(attrName, resValue.getValue());
    692                         }
    693 
    694                         resValue = mRenderResources.resolveResValue(resValue);
    695                     }
    696 
    697                     ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
    698                 } else {
    699                     // there is a value in the XML, but we need to resolve it in case it's
    700                     // referencing another resource or a theme value.
    701                     ta.bridgeSetValue(index, attrName, frameworkAttr,
    702                             mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
    703                 }
    704             }
    705         }
    706 
    707         ta.sealArray();
    708 
    709         return ta;
    710     }
    711 
    712     @Override
    713     public Looper getMainLooper() {
    714         return Looper.myLooper();
    715     }
    716 
    717 
    718     // ------------- private new methods
    719 
    720     /**
    721      * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
    722      * values found in the given style.
    723      * @see #obtainStyledAttributes(int, int[])
    724      */
    725     private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs)
    726             throws Resources.NotFoundException {
    727 
    728         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
    729 
    730         BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
    731                 false);
    732 
    733         // for each attribute, get its name so that we can search it in the style
    734         for (int i = 0 ; i < attrs.length ; i++) {
    735             Pair<String, Boolean> attribute = attributes.get(i);
    736 
    737             if (attribute != null) {
    738                 // look for the value in the given style
    739                 ResourceValue resValue = mRenderResources.findItemInStyle(style,
    740                         attribute.getFirst(), attribute.getSecond());
    741 
    742                 if (resValue != null) {
    743                     // resolve it to make sure there are no references left.
    744                     ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
    745                             mRenderResources.resolveResValue(resValue));
    746                 }
    747             }
    748         }
    749 
    750         ta.sealArray();
    751 
    752         return ta;
    753     }
    754 
    755 
    756     /**
    757      * The input int[] attrs is a list of attributes. The returns a list of information about
    758      * each attributes. The information is (name, isFramework)
    759      * <p/>
    760      *
    761      * @param attrs An attribute array reference given to obtainStyledAttributes.
    762      * @return List of attribute information.
    763      */
    764     private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
    765         List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
    766 
    767         // for each attribute, get its name so that we can search it in the style
    768         for (int i = 0 ; i < attrs.length ; i++) {
    769             Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]);
    770             boolean isFramework = false;
    771             if (resolvedResource != null) {
    772                 isFramework = true;
    773             } else {
    774                 resolvedResource = mProjectCallback.resolveResourceId(attrs[i]);
    775             }
    776 
    777             if (resolvedResource != null) {
    778                 results.add(Pair.of(resolvedResource.getSecond(), isFramework));
    779             } else {
    780                 results.add(null);
    781             }
    782         }
    783 
    784         return results;
    785     }
    786 
    787     /**
    788      * Searches for the attribute referenced by its internal id.
    789      *
    790      * @param attr An attribute reference given to obtainStyledAttributes such as defStyle.
    791      * @return A (name, isFramework) pair describing the attribute if found. Returns null
    792      *         if nothing is found.
    793      */
    794     public Pair<String, Boolean> searchAttr(int attr) {
    795         Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
    796         if (info != null) {
    797             return Pair.of(info.getSecond(), Boolean.TRUE);
    798         }
    799 
    800         info = mProjectCallback.resolveResourceId(attr);
    801         if (info != null) {
    802             return Pair.of(info.getSecond(), Boolean.FALSE);
    803         }
    804 
    805         return null;
    806     }
    807 
    808     public int getDynamicIdByStyle(StyleResourceValue resValue) {
    809         if (mDynamicIdToStyleMap == null) {
    810             // create the maps.
    811             mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>();
    812             mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>();
    813         }
    814 
    815         // look for an existing id
    816         Integer id = mStyleToDynamicIdMap.get(resValue);
    817 
    818         if (id == null) {
    819             // generate a new id
    820             id = Integer.valueOf(++mDynamicIdGenerator);
    821 
    822             // and add it to the maps.
    823             mDynamicIdToStyleMap.put(id, resValue);
    824             mStyleToDynamicIdMap.put(resValue, id);
    825         }
    826 
    827         return id;
    828     }
    829 
    830     private StyleResourceValue getStyleByDynamicId(int i) {
    831         if (mDynamicIdToStyleMap != null) {
    832             return mDynamicIdToStyleMap.get(i);
    833         }
    834 
    835         return null;
    836     }
    837 
    838     public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) {
    839         Integer value = Bridge.getResourceId(resType, resName);
    840         if (value != null) {
    841             return value.intValue();
    842         }
    843 
    844         return defValue;
    845     }
    846 
    847     public int getProjectResourceValue(ResourceType resType, String resName, int defValue) {
    848         if (mProjectCallback != null) {
    849             Integer value = mProjectCallback.getResourceId(resType, resName);
    850             if (value != null) {
    851                 return value.intValue();
    852             }
    853         }
    854 
    855         return defValue;
    856     }
    857 
    858     //------------ NOT OVERRIDEN --------------------
    859 
    860     @Override
    861     public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
    862         // pass
    863         return false;
    864     }
    865 
    866     @Override
    867     public int checkCallingOrSelfPermission(String arg0) {
    868         // pass
    869         return 0;
    870     }
    871 
    872     @Override
    873     public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
    874         // pass
    875         return 0;
    876     }
    877 
    878     @Override
    879     public int checkCallingPermission(String arg0) {
    880         // pass
    881         return 0;
    882     }
    883 
    884     @Override
    885     public int checkCallingUriPermission(Uri arg0, int arg1) {
    886         // pass
    887         return 0;
    888     }
    889 
    890     @Override
    891     public int checkPermission(String arg0, int arg1, int arg2) {
    892         // pass
    893         return 0;
    894     }
    895 
    896     @Override
    897     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
    898         // pass
    899         return 0;
    900     }
    901 
    902     @Override
    903     public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
    904             int arg4, int arg5) {
    905         // pass
    906         return 0;
    907     }
    908 
    909     @Override
    910     public void clearWallpaper() {
    911         // pass
    912 
    913     }
    914 
    915     @Override
    916     public Context createPackageContext(String arg0, int arg1) {
    917         // pass
    918         return null;
    919     }
    920 
    921     @Override
    922     public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
    923         // pass
    924         return null;
    925     }
    926 
    927     @Override
    928     public Context createConfigurationContext(Configuration overrideConfiguration) {
    929         // pass
    930         return null;
    931     }
    932 
    933     @Override
    934     public Context createDisplayContext(Display display) {
    935         // pass
    936         return null;
    937     }
    938 
    939     @Override
    940     public String[] databaseList() {
    941         // pass
    942         return null;
    943     }
    944 
    945     @Override
    946     public boolean deleteDatabase(String arg0) {
    947         // pass
    948         return false;
    949     }
    950 
    951     @Override
    952     public boolean deleteFile(String arg0) {
    953         // pass
    954         return false;
    955     }
    956 
    957     @Override
    958     public void enforceCallingOrSelfPermission(String arg0, String arg1) {
    959         // pass
    960 
    961     }
    962 
    963     @Override
    964     public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
    965             String arg2) {
    966         // pass
    967 
    968     }
    969 
    970     @Override
    971     public void enforceCallingPermission(String arg0, String arg1) {
    972         // pass
    973 
    974     }
    975 
    976     @Override
    977     public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
    978         // pass
    979 
    980     }
    981 
    982     @Override
    983     public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
    984         // pass
    985 
    986     }
    987 
    988     @Override
    989     public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
    990             String arg4) {
    991         // pass
    992 
    993     }
    994 
    995     @Override
    996     public void enforceUriPermission(Uri arg0, String arg1, String arg2,
    997             int arg3, int arg4, int arg5, String arg6) {
    998         // pass
    999 
   1000     }
   1001 
   1002     @Override
   1003     public String[] fileList() {
   1004         // pass
   1005         return null;
   1006     }
   1007 
   1008     @Override
   1009     public AssetManager getAssets() {
   1010         // pass
   1011         return null;
   1012     }
   1013 
   1014     @Override
   1015     public File getCacheDir() {
   1016         // pass
   1017         return null;
   1018     }
   1019 
   1020     @Override
   1021     public File getExternalCacheDir() {
   1022         // pass
   1023         return null;
   1024     }
   1025 
   1026     @Override
   1027     public ContentResolver getContentResolver() {
   1028         if (mContentResolver == null) {
   1029             mContentResolver = new BridgeContentResolver(this);
   1030         }
   1031         return mContentResolver;
   1032     }
   1033 
   1034     @Override
   1035     public File getDatabasePath(String arg0) {
   1036         // pass
   1037         return null;
   1038     }
   1039 
   1040     @Override
   1041     public File getDir(String arg0, int arg1) {
   1042         // pass
   1043         return null;
   1044     }
   1045 
   1046     @Override
   1047     public File getFileStreamPath(String arg0) {
   1048         // pass
   1049         return null;
   1050     }
   1051 
   1052     @Override
   1053     public File getFilesDir() {
   1054         // pass
   1055         return null;
   1056     }
   1057 
   1058     @Override
   1059     public File getExternalFilesDir(String type) {
   1060         // pass
   1061         return null;
   1062     }
   1063 
   1064     @Override
   1065     public String getPackageCodePath() {
   1066         // pass
   1067         return null;
   1068     }
   1069 
   1070     @Override
   1071     public PackageManager getPackageManager() {
   1072         // pass
   1073         return null;
   1074     }
   1075 
   1076     @Override
   1077     public String getPackageName() {
   1078         // pass
   1079         return null;
   1080     }
   1081 
   1082     @Override
   1083     public String getBasePackageName() {
   1084         // pass
   1085         return null;
   1086     }
   1087 
   1088     @Override
   1089     public ApplicationInfo getApplicationInfo() {
   1090         return mApplicationInfo;
   1091     }
   1092 
   1093     @Override
   1094     public String getPackageResourcePath() {
   1095         // pass
   1096         return null;
   1097     }
   1098 
   1099     @Override
   1100     public File getSharedPrefsFile(String name) {
   1101         // pass
   1102         return null;
   1103     }
   1104 
   1105     @Override
   1106     public SharedPreferences getSharedPreferences(String arg0, int arg1) {
   1107         // pass
   1108         return null;
   1109     }
   1110 
   1111     @Override
   1112     public Drawable getWallpaper() {
   1113         // pass
   1114         return null;
   1115     }
   1116 
   1117     @Override
   1118     public int getWallpaperDesiredMinimumWidth() {
   1119         return -1;
   1120     }
   1121 
   1122     @Override
   1123     public int getWallpaperDesiredMinimumHeight() {
   1124         return -1;
   1125     }
   1126 
   1127     @Override
   1128     public void grantUriPermission(String arg0, Uri arg1, int arg2) {
   1129         // pass
   1130 
   1131     }
   1132 
   1133     @Override
   1134     public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
   1135         // pass
   1136         return null;
   1137     }
   1138 
   1139     @Override
   1140     public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
   1141         // pass
   1142         return null;
   1143     }
   1144 
   1145     @Override
   1146     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
   1147         // pass
   1148         return null;
   1149     }
   1150 
   1151     @Override
   1152     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
   1153             CursorFactory arg2, DatabaseErrorHandler arg3) {
   1154         // pass
   1155         return null;
   1156     }
   1157 
   1158     @Override
   1159     public Drawable peekWallpaper() {
   1160         // pass
   1161         return null;
   1162     }
   1163 
   1164     @Override
   1165     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
   1166         // pass
   1167         return null;
   1168     }
   1169 
   1170     @Override
   1171     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
   1172             String arg2, Handler arg3) {
   1173         // pass
   1174         return null;
   1175     }
   1176 
   1177     @Override
   1178     public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
   1179             IntentFilter arg1, String arg2, Handler arg3) {
   1180         // pass
   1181         return null;
   1182     }
   1183 
   1184     @Override
   1185     public void removeStickyBroadcast(Intent arg0) {
   1186         // pass
   1187 
   1188     }
   1189 
   1190     @Override
   1191     public void revokeUriPermission(Uri arg0, int arg1) {
   1192         // pass
   1193 
   1194     }
   1195 
   1196     @Override
   1197     public void sendBroadcast(Intent arg0) {
   1198         // pass
   1199 
   1200     }
   1201 
   1202     @Override
   1203     public void sendBroadcast(Intent arg0, String arg1) {
   1204         // pass
   1205 
   1206     }
   1207 
   1208     @Override
   1209     public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
   1210         // pass
   1211     }
   1212 
   1213     @Override
   1214     public void sendOrderedBroadcast(Intent arg0, String arg1) {
   1215         // pass
   1216 
   1217     }
   1218 
   1219     @Override
   1220     public void sendOrderedBroadcast(Intent arg0, String arg1,
   1221             BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
   1222             Bundle arg6) {
   1223         // pass
   1224 
   1225     }
   1226 
   1227     @Override
   1228     public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
   1229             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
   1230             String initialData, Bundle initialExtras) {
   1231         // pass
   1232     }
   1233 
   1234     @Override
   1235     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
   1236         // pass
   1237     }
   1238 
   1239     @Override
   1240     public void sendBroadcastAsUser(Intent intent, UserHandle user,
   1241             String receiverPermission) {
   1242         // pass
   1243     }
   1244 
   1245     @Override
   1246     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
   1247             String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
   1248             int initialCode, String initialData, Bundle initialExtras) {
   1249         // pass
   1250     }
   1251 
   1252     @Override
   1253     public void sendStickyBroadcast(Intent arg0) {
   1254         // pass
   1255 
   1256     }
   1257 
   1258     @Override
   1259     public void sendStickyOrderedBroadcast(Intent intent,
   1260             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
   1261            Bundle initialExtras) {
   1262         // pass
   1263     }
   1264 
   1265     @Override
   1266     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
   1267         // pass
   1268     }
   1269 
   1270     @Override
   1271     public void sendStickyOrderedBroadcastAsUser(Intent intent,
   1272             UserHandle user, BroadcastReceiver resultReceiver,
   1273             Handler scheduler, int initialCode, String initialData,
   1274             Bundle initialExtras) {
   1275         // pass
   1276     }
   1277 
   1278     @Override
   1279     public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
   1280         // pass
   1281     }
   1282 
   1283     @Override
   1284     public void setTheme(int arg0) {
   1285         // pass
   1286 
   1287     }
   1288 
   1289     @Override
   1290     public void setWallpaper(Bitmap arg0) throws IOException {
   1291         // pass
   1292 
   1293     }
   1294 
   1295     @Override
   1296     public void setWallpaper(InputStream arg0) throws IOException {
   1297         // pass
   1298 
   1299     }
   1300 
   1301     @Override
   1302     public void startActivity(Intent arg0) {
   1303         // pass
   1304     }
   1305 
   1306     @Override
   1307     public void startActivity(Intent arg0, Bundle arg1) {
   1308         // pass
   1309     }
   1310 
   1311     @Override
   1312     public void startIntentSender(IntentSender intent,
   1313             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
   1314             throws IntentSender.SendIntentException {
   1315         // pass
   1316     }
   1317 
   1318     @Override
   1319     public void startIntentSender(IntentSender intent,
   1320             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
   1321             Bundle options) throws IntentSender.SendIntentException {
   1322         // pass
   1323     }
   1324 
   1325     @Override
   1326     public boolean startInstrumentation(ComponentName arg0, String arg1,
   1327             Bundle arg2) {
   1328         // pass
   1329         return false;
   1330     }
   1331 
   1332     @Override
   1333     public ComponentName startService(Intent arg0) {
   1334         // pass
   1335         return null;
   1336     }
   1337 
   1338     @Override
   1339     public boolean stopService(Intent arg0) {
   1340         // pass
   1341         return false;
   1342     }
   1343 
   1344     @Override
   1345     public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
   1346         // pass
   1347         return null;
   1348     }
   1349 
   1350     @Override
   1351     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
   1352         // pass
   1353         return false;
   1354     }
   1355 
   1356     @Override
   1357     public void unbindService(ServiceConnection arg0) {
   1358         // pass
   1359 
   1360     }
   1361 
   1362     @Override
   1363     public void unregisterReceiver(BroadcastReceiver arg0) {
   1364         // pass
   1365 
   1366     }
   1367 
   1368     @Override
   1369     public Context getApplicationContext() {
   1370         return this;
   1371     }
   1372 
   1373     @Override
   1374     public void startActivities(Intent[] arg0) {
   1375         // pass
   1376 
   1377     }
   1378 
   1379     @Override
   1380     public void startActivities(Intent[] arg0, Bundle arg1) {
   1381         // pass
   1382 
   1383     }
   1384 
   1385     @Override
   1386     public boolean isRestricted() {
   1387         return false;
   1388     }
   1389 
   1390     @Override
   1391     public File getObbDir() {
   1392         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
   1393         return null;
   1394     }
   1395 
   1396     @Override
   1397     public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
   1398         // pass
   1399         return null;
   1400     }
   1401 
   1402     /**
   1403      * @hide
   1404      */
   1405     @Override
   1406     public int getUserId() {
   1407         return 0; // not used
   1408     }
   1409 }
   1410