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