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