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