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