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