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