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