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