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