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