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