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