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