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