• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.layoutlib.bridge.android;
18 
19 import com.android.SdkConstants;
20 import com.android.ide.common.rendering.api.AssetRepository;
21 import com.android.ide.common.rendering.api.ILayoutPullParser;
22 import com.android.ide.common.rendering.api.LayoutLog;
23 import com.android.ide.common.rendering.api.LayoutlibCallback;
24 import com.android.ide.common.rendering.api.RenderResources;
25 import com.android.ide.common.rendering.api.ResourceReference;
26 import com.android.ide.common.rendering.api.ResourceValue;
27 import com.android.ide.common.rendering.api.StyleResourceValue;
28 import com.android.layoutlib.bridge.Bridge;
29 import com.android.layoutlib.bridge.BridgeConstants;
30 import com.android.layoutlib.bridge.android.view.WindowManagerImpl;
31 import com.android.layoutlib.bridge.impl.ParserFactory;
32 import com.android.layoutlib.bridge.impl.Stack;
33 import com.android.resources.ResourceType;
34 import com.android.util.Pair;
35 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, @NonNull DisplayMetrics metrics, @NonNull RenderResources renderResources, @NonNull AssetRepository assets, @NonNull LayoutlibCallback layoutlibCallback, @NonNull Configuration config, int targetSdkVersion, boolean hasRtlSupport)215     public BridgeContext(Object projectKey, @NonNull DisplayMetrics metrics,
216             @NonNull RenderResources renderResources,
217             @NonNull AssetRepository assets,
218             @NonNull LayoutlibCallback layoutlibCallback,
219             @NonNull 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<AttributeHolder> 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                 AttributeHolder attributeHolder = attributeList.get(index);
870 
871                 if (attributeHolder == null) {
872                     continue;
873                 }
874 
875                 String attrName = attributeHolder.name;
876                 boolean frameworkAttr = attributeHolder.isFramework;
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, attributeHolder.resourceId,
969                             defaultValue);
970                 } else {
971                     // there is a value in the XML, but we need to resolve it in case it's
972                     // referencing another resource or a theme value.
973                     ta.bridgeSetValue(index, attrName, frameworkAttr, attributeHolder.resourceId,
974                             mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
975                 }
976             }
977         }
978 
979         ta.sealArray();
980 
981         return ta;
982     }
983 
984     @Override
getMainLooper()985     public Looper getMainLooper() {
986         return Looper.myLooper();
987     }
988 
989 
990     @Override
getPackageName()991     public String getPackageName() {
992         if (mApplicationInfo.packageName == null) {
993             mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE);
994         }
995         return mApplicationInfo.packageName;
996     }
997 
998     @Override
getPackageManager()999     public PackageManager getPackageManager() {
1000         if (mPackageManager == null) {
1001             mPackageManager = new BridgePackageManager();
1002         }
1003         return mPackageManager;
1004     }
1005 
1006     // ------------- private new methods
1007 
1008     /**
1009      * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
1010      * values found in the given style. If no style is specified, the default theme, along with the
1011      * styles applied to it are used.
1012      *
1013      * @see #obtainStyledAttributes(int, int[])
1014      */
createStyleBasedTypedArray( @ullable StyleResourceValue style, int[] attrs)1015     private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
1016             @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
1017         List<AttributeHolder> attributes = searchAttrs(attrs);
1018 
1019         BridgeTypedArray ta =
1020                 Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
1021 
1022         PropertiesMap defaultPropMap = new PropertiesMap();
1023         // for each attribute, get its name so that we can search it in the style
1024         for (int i = 0; i < attrs.length; i++) {
1025             AttributeHolder attrHolder = attributes.get(i);
1026 
1027             if (attrHolder != null) {
1028                 // look for the value in the given style
1029                 ResourceValue resValue;
1030                 String attrName = attrHolder.name;
1031                 boolean frameworkAttr = attrHolder.isFramework;
1032                 if (style != null) {
1033                     resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr);
1034                 } else {
1035                     resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
1036                 }
1037 
1038                 if (resValue != null) {
1039                     // Add it to defaultPropMap before resolving
1040                     String preResolve = resValue.getValue();
1041                     // resolve it to make sure there are no references left.
1042                     resValue = mRenderResources.resolveResValue(resValue);
1043                     ta.bridgeSetValue(i, attrName, frameworkAttr, attrHolder.resourceId,
1044                             resValue);
1045                     defaultPropMap.put(
1046                             frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName,
1047                             new Property(preResolve, resValue.getValue()));
1048                 }
1049             }
1050         }
1051 
1052         ta.sealArray();
1053 
1054         return Pair.of(ta, defaultPropMap);
1055     }
1056 
1057     /**
1058      * The input int[] attributeIds is a list of attributes. The returns a list of information about
1059      * each attributes. The information is (name, isFramework)
1060      * <p/>
1061      *
1062      * @param attributeIds An attribute array reference given to obtainStyledAttributes.
1063      * @return List of attribute information.
1064      */
searchAttrs(int[] attributeIds)1065     private List<AttributeHolder> searchAttrs(int[] attributeIds) {
1066         List<AttributeHolder> results = new ArrayList<>(attributeIds.length);
1067 
1068         // for each attribute, get its name so that we can search it in the style
1069         for (int id : attributeIds) {
1070             Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(id);
1071             boolean isFramework = false;
1072             if (resolvedResource != null) {
1073                 isFramework = true;
1074             } else {
1075                 resolvedResource = mLayoutlibCallback.resolveResourceId(id);
1076             }
1077 
1078             if (resolvedResource != null) {
1079                 results.add(new AttributeHolder(id, resolvedResource.getSecond(), isFramework));
1080             } else {
1081                 results.add(null);
1082             }
1083         }
1084 
1085         return results;
1086     }
1087 
1088     /**
1089      * Searches for the attribute referenced by its internal id.
1090      *
1091      * @param attr An attribute reference given to obtainStyledAttributes such as defStyle.
1092      * @return A (name, isFramework) pair describing the attribute if found. Returns null
1093      *         if nothing is found.
1094      */
searchAttr(int attr)1095     private Pair<String, Boolean> searchAttr(int attr) {
1096         Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
1097         if (info != null) {
1098             return Pair.of(info.getSecond(), Boolean.TRUE);
1099         }
1100 
1101         info = mLayoutlibCallback.resolveResourceId(attr);
1102         if (info != null) {
1103             return Pair.of(info.getSecond(), Boolean.FALSE);
1104         }
1105 
1106         return null;
1107     }
1108 
getDynamicIdByStyle(StyleResourceValue resValue)1109     public int getDynamicIdByStyle(StyleResourceValue resValue) {
1110         if (mDynamicIdToStyleMap == null) {
1111             // create the maps.
1112             mDynamicIdToStyleMap = new HashMap<>();
1113             mStyleToDynamicIdMap = new HashMap<>();
1114         }
1115 
1116         // look for an existing id
1117         Integer id = mStyleToDynamicIdMap.get(resValue);
1118 
1119         if (id == null) {
1120             // generate a new id
1121             id = ++mDynamicIdGenerator;
1122 
1123             // and add it to the maps.
1124             mDynamicIdToStyleMap.put(id, resValue);
1125             mStyleToDynamicIdMap.put(resValue, id);
1126         }
1127 
1128         return id;
1129     }
1130 
getStyleByDynamicId(int i)1131     private StyleResourceValue getStyleByDynamicId(int i) {
1132         if (mDynamicIdToStyleMap != null) {
1133             return mDynamicIdToStyleMap.get(i);
1134         }
1135 
1136         return null;
1137     }
1138 
getFrameworkResourceValue(ResourceType resType, String resName, int defValue)1139     public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) {
1140         if (getRenderResources().getFrameworkResource(resType, resName) != null) {
1141             // Bridge.getResourceId creates a new resource id if an existing one isn't found. So,
1142             // we check for the existence of the resource before calling it.
1143             return Bridge.getResourceId(resType, resName);
1144         }
1145 
1146         return defValue;
1147     }
1148 
getProjectResourceValue(ResourceType resType, String resName, int defValue)1149     public int getProjectResourceValue(ResourceType resType, String resName, int defValue) {
1150         // getResourceId creates a new resource id if an existing resource id isn't found. So, we
1151         // check for the existence of the resource before calling it.
1152         if (getRenderResources().getProjectResource(resType, resName) != null) {
1153             if (mLayoutlibCallback != null) {
1154                 Integer value = mLayoutlibCallback.getResourceId(resType, resName);
1155                 if (value != null) {
1156                     return value;
1157                 }
1158             }
1159         }
1160 
1161         return defValue;
1162     }
1163 
getBaseContext(Context context)1164     public static Context getBaseContext(Context context) {
1165         while (context instanceof ContextWrapper) {
1166             context = ((ContextWrapper) context).getBaseContext();
1167         }
1168         return context;
1169     }
1170 
getBinder()1171     public IBinder getBinder() {
1172         if (mBinder == null) {
1173             // create a dummy binder. We only need it be not null.
1174             mBinder = new IBinder() {
1175                 @Override
1176                 public String getInterfaceDescriptor() throws RemoteException {
1177                     return null;
1178                 }
1179 
1180                 @Override
1181                 public boolean pingBinder() {
1182                     return false;
1183                 }
1184 
1185                 @Override
1186                 public boolean isBinderAlive() {
1187                     return false;
1188                 }
1189 
1190                 @Override
1191                 public IInterface queryLocalInterface(String descriptor) {
1192                     return null;
1193                 }
1194 
1195                 @Override
1196                 public void dump(FileDescriptor fd, String[] args) throws RemoteException {
1197 
1198                 }
1199 
1200                 @Override
1201                 public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
1202 
1203                 }
1204 
1205                 @Override
1206                 public boolean transact(int code, Parcel data, Parcel reply, int flags)
1207                         throws RemoteException {
1208                     return false;
1209                 }
1210 
1211                 @Override
1212                 public void linkToDeath(DeathRecipient recipient, int flags)
1213                         throws RemoteException {
1214 
1215                 }
1216 
1217                 @Override
1218                 public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
1219                     return false;
1220                 }
1221 
1222                 @Override
1223                 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1224                   String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) {
1225                 }
1226             };
1227         }
1228         return mBinder;
1229     }
1230 
1231     //------------ NOT OVERRIDEN --------------------
1232 
1233     @Override
bindService(Intent arg0, ServiceConnection arg1, int arg2)1234     public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
1235         // pass
1236         return false;
1237     }
1238 
1239     @Override
checkCallingOrSelfPermission(String arg0)1240     public int checkCallingOrSelfPermission(String arg0) {
1241         // pass
1242         return 0;
1243     }
1244 
1245     @Override
checkCallingOrSelfUriPermission(Uri arg0, int arg1)1246     public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
1247         // pass
1248         return 0;
1249     }
1250 
1251     @Override
checkCallingPermission(String arg0)1252     public int checkCallingPermission(String arg0) {
1253         // pass
1254         return 0;
1255     }
1256 
1257     @Override
checkCallingUriPermission(Uri arg0, int arg1)1258     public int checkCallingUriPermission(Uri arg0, int arg1) {
1259         // pass
1260         return 0;
1261     }
1262 
1263     @Override
checkPermission(String arg0, int arg1, int arg2)1264     public int checkPermission(String arg0, int arg1, int arg2) {
1265         // pass
1266         return 0;
1267     }
1268 
1269     @Override
checkSelfPermission(String arg0)1270     public int checkSelfPermission(String arg0) {
1271         // pass
1272         return 0;
1273     }
1274 
1275     @Override
checkPermission(String arg0, int arg1, int arg2, IBinder arg3)1276     public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
1277         // pass
1278         return 0;
1279     }
1280 
1281     @Override
checkUriPermission(Uri arg0, int arg1, int arg2, int arg3)1282     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
1283         // pass
1284         return 0;
1285     }
1286 
1287     @Override
checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4)1288     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) {
1289         // pass
1290         return 0;
1291     }
1292 
1293     @Override
checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5)1294     public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
1295             int arg4, int arg5) {
1296         // pass
1297         return 0;
1298     }
1299 
1300     @Override
clearWallpaper()1301     public void clearWallpaper() {
1302         // pass
1303 
1304     }
1305 
1306     @Override
createPackageContext(String arg0, int arg1)1307     public Context createPackageContext(String arg0, int arg1) {
1308         // pass
1309         return null;
1310     }
1311 
1312     @Override
createPackageContextAsUser(String arg0, int arg1, UserHandle user)1313     public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
1314         // pass
1315         return null;
1316     }
1317 
1318     @Override
createConfigurationContext(Configuration overrideConfiguration)1319     public Context createConfigurationContext(Configuration overrideConfiguration) {
1320         // pass
1321         return null;
1322     }
1323 
1324     @Override
createDisplayContext(Display display)1325     public Context createDisplayContext(Display display) {
1326         // pass
1327         return null;
1328     }
1329 
1330     @Override
createContextForSplit(String splitName)1331     public Context createContextForSplit(String splitName) {
1332         // pass
1333         return null;
1334     }
1335 
1336     @Override
databaseList()1337     public String[] databaseList() {
1338         // pass
1339         return null;
1340     }
1341 
1342     @Override
createApplicationContext(ApplicationInfo application, int flags)1343     public Context createApplicationContext(ApplicationInfo application, int flags)
1344             throws PackageManager.NameNotFoundException {
1345         return null;
1346     }
1347 
1348     @Override
moveDatabaseFrom(Context sourceContext, String name)1349     public boolean moveDatabaseFrom(Context sourceContext, String name) {
1350         // pass
1351         return false;
1352     }
1353 
1354     @Override
deleteDatabase(String arg0)1355     public boolean deleteDatabase(String arg0) {
1356         // pass
1357         return false;
1358     }
1359 
1360     @Override
deleteFile(String arg0)1361     public boolean deleteFile(String arg0) {
1362         // pass
1363         return false;
1364     }
1365 
1366     @Override
enforceCallingOrSelfPermission(String arg0, String arg1)1367     public void enforceCallingOrSelfPermission(String arg0, String arg1) {
1368         // pass
1369 
1370     }
1371 
1372     @Override
enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2)1373     public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
1374             String arg2) {
1375         // pass
1376 
1377     }
1378 
1379     @Override
enforceCallingPermission(String arg0, String arg1)1380     public void enforceCallingPermission(String arg0, String arg1) {
1381         // pass
1382 
1383     }
1384 
1385     @Override
enforceCallingUriPermission(Uri arg0, int arg1, String arg2)1386     public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
1387         // pass
1388 
1389     }
1390 
1391     @Override
enforcePermission(String arg0, int arg1, int arg2, String arg3)1392     public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
1393         // pass
1394 
1395     }
1396 
1397     @Override
enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4)1398     public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
1399             String arg4) {
1400         // pass
1401 
1402     }
1403 
1404     @Override
enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6)1405     public void enforceUriPermission(Uri arg0, String arg1, String arg2,
1406             int arg3, int arg4, int arg5, String arg6) {
1407         // pass
1408 
1409     }
1410 
1411     @Override
fileList()1412     public String[] fileList() {
1413         // pass
1414         return null;
1415     }
1416 
1417     @Override
getAssets()1418     public BridgeAssetManager getAssets() {
1419         return mAssets;
1420     }
1421 
1422     @Override
getCacheDir()1423     public File getCacheDir() {
1424         // pass
1425         return null;
1426     }
1427 
1428     @Override
getCodeCacheDir()1429     public File getCodeCacheDir() {
1430         // pass
1431         return null;
1432     }
1433 
1434     @Override
getExternalCacheDir()1435     public File getExternalCacheDir() {
1436         // pass
1437         return null;
1438     }
1439 
1440     @Override
getPreloadsFileCache()1441     public File getPreloadsFileCache() {
1442         // pass
1443         return null;
1444     }
1445 
1446     @Override
getContentResolver()1447     public ContentResolver getContentResolver() {
1448         if (mContentResolver == null) {
1449             mContentResolver = new BridgeContentResolver(this);
1450         }
1451         return mContentResolver;
1452     }
1453 
1454     @Override
getDatabasePath(String arg0)1455     public File getDatabasePath(String arg0) {
1456         // pass
1457         return null;
1458     }
1459 
1460     @Override
getDir(String arg0, int arg1)1461     public File getDir(String arg0, int arg1) {
1462         // pass
1463         return null;
1464     }
1465 
1466     @Override
getFileStreamPath(String arg0)1467     public File getFileStreamPath(String arg0) {
1468         // pass
1469         return null;
1470     }
1471 
1472     @Override
getSharedPreferencesPath(String name)1473     public File getSharedPreferencesPath(String name) {
1474         // pass
1475         return null;
1476     }
1477 
1478     @Override
getDataDir()1479     public File getDataDir() {
1480         // pass
1481         return null;
1482     }
1483 
1484     @Override
getFilesDir()1485     public File getFilesDir() {
1486         // pass
1487         return null;
1488     }
1489 
1490     @Override
getNoBackupFilesDir()1491     public File getNoBackupFilesDir() {
1492         // pass
1493         return null;
1494     }
1495 
1496     @Override
getExternalFilesDir(String type)1497     public File getExternalFilesDir(String type) {
1498         // pass
1499         return null;
1500     }
1501 
1502     @Override
getPackageCodePath()1503     public String getPackageCodePath() {
1504         // pass
1505         return null;
1506     }
1507 
1508     @Override
getBasePackageName()1509     public String getBasePackageName() {
1510         // pass
1511         return null;
1512     }
1513 
1514     @Override
getOpPackageName()1515     public String getOpPackageName() {
1516         // pass
1517         return null;
1518     }
1519 
1520     @Override
getApplicationInfo()1521     public ApplicationInfo getApplicationInfo() {
1522         return mApplicationInfo;
1523     }
1524 
1525     @Override
getPackageResourcePath()1526     public String getPackageResourcePath() {
1527         // pass
1528         return null;
1529     }
1530 
1531     @Override
getSharedPreferences(String arg0, int arg1)1532     public SharedPreferences getSharedPreferences(String arg0, int arg1) {
1533         if (mSharedPreferences == null) {
1534             mSharedPreferences = new BridgeSharedPreferences();
1535         }
1536         return mSharedPreferences;
1537     }
1538 
1539     @Override
getSharedPreferences(File arg0, int arg1)1540     public SharedPreferences getSharedPreferences(File arg0, int arg1) {
1541         if (mSharedPreferences == null) {
1542             mSharedPreferences = new BridgeSharedPreferences();
1543         }
1544         return mSharedPreferences;
1545     }
1546 
1547     @Override
reloadSharedPreferences()1548     public void reloadSharedPreferences() {
1549         // intentional noop
1550     }
1551 
1552     @Override
moveSharedPreferencesFrom(Context sourceContext, String name)1553     public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
1554         // pass
1555         return false;
1556     }
1557 
1558     @Override
deleteSharedPreferences(String name)1559     public boolean deleteSharedPreferences(String name) {
1560         // pass
1561         return false;
1562     }
1563 
1564     @Override
getWallpaper()1565     public Drawable getWallpaper() {
1566         // pass
1567         return null;
1568     }
1569 
1570     @Override
getWallpaperDesiredMinimumWidth()1571     public int getWallpaperDesiredMinimumWidth() {
1572         return -1;
1573     }
1574 
1575     @Override
getWallpaperDesiredMinimumHeight()1576     public int getWallpaperDesiredMinimumHeight() {
1577         return -1;
1578     }
1579 
1580     @Override
grantUriPermission(String arg0, Uri arg1, int arg2)1581     public void grantUriPermission(String arg0, Uri arg1, int arg2) {
1582         // pass
1583 
1584     }
1585 
1586     @Override
openFileInput(String arg0)1587     public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
1588         // pass
1589         return null;
1590     }
1591 
1592     @Override
openFileOutput(String arg0, int arg1)1593     public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
1594         // pass
1595         return null;
1596     }
1597 
1598     @Override
openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2)1599     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
1600         // pass
1601         return null;
1602     }
1603 
1604     @Override
openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2, DatabaseErrorHandler arg3)1605     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
1606             CursorFactory arg2, DatabaseErrorHandler arg3) {
1607         // pass
1608         return null;
1609     }
1610 
1611     @Override
peekWallpaper()1612     public Drawable peekWallpaper() {
1613         // pass
1614         return null;
1615     }
1616 
1617     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1)1618     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
1619         // pass
1620         return null;
1621     }
1622 
1623     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2)1624     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2) {
1625         // pass
1626         return null;
1627     }
1628 
1629     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3)1630     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
1631             String arg2, Handler arg3) {
1632         // pass
1633         return null;
1634     }
1635 
1636     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3, int arg4)1637     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
1638             String arg2, Handler arg3, int arg4) {
1639         // pass
1640         return null;
1641     }
1642 
1643     @Override
registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3)1644     public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
1645             IntentFilter arg1, String arg2, Handler arg3) {
1646         // pass
1647         return null;
1648     }
1649 
1650     @Override
removeStickyBroadcast(Intent arg0)1651     public void removeStickyBroadcast(Intent arg0) {
1652         // pass
1653 
1654     }
1655 
1656     @Override
revokeUriPermission(Uri arg0, int arg1)1657     public void revokeUriPermission(Uri arg0, int arg1) {
1658         // pass
1659 
1660     }
1661 
1662     @Override
revokeUriPermission(String arg0, Uri arg1, int arg2)1663     public void revokeUriPermission(String arg0, Uri arg1, int arg2) {
1664         // pass
1665 
1666     }
1667 
1668     @Override
sendBroadcast(Intent arg0)1669     public void sendBroadcast(Intent arg0) {
1670         // pass
1671 
1672     }
1673 
1674     @Override
sendBroadcast(Intent arg0, String arg1)1675     public void sendBroadcast(Intent arg0, String arg1) {
1676         // pass
1677 
1678     }
1679 
1680     @Override
sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)1681     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
1682         // pass
1683 
1684     }
1685 
1686     @Override
sendBroadcast(Intent arg0, String arg1, Bundle arg2)1687     public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) {
1688         // pass
1689 
1690     }
1691 
1692     @Override
sendBroadcast(Intent intent, String receiverPermission, int appOp)1693     public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
1694         // pass
1695     }
1696 
1697     @Override
sendOrderedBroadcast(Intent arg0, String arg1)1698     public void sendOrderedBroadcast(Intent arg0, String arg1) {
1699         // pass
1700 
1701     }
1702 
1703     @Override
sendOrderedBroadcast(Intent arg0, String arg1, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1704     public void sendOrderedBroadcast(Intent arg0, String arg1,
1705             BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
1706             Bundle arg6) {
1707         // pass
1708 
1709     }
1710 
1711     @Override
sendOrderedBroadcast(Intent arg0, String arg1, Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1712     public void sendOrderedBroadcast(Intent arg0, String arg1,
1713             Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
1714             Bundle arg6) {
1715         // pass
1716 
1717     }
1718 
1719     @Override
sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1720     public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
1721             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
1722             String initialData, Bundle initialExtras) {
1723         // pass
1724     }
1725 
1726     @Override
sendBroadcastAsUser(Intent intent, UserHandle user)1727     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
1728         // pass
1729     }
1730 
1731     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)1732     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1733             String receiverPermission) {
1734         // pass
1735     }
1736 
1737     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options)1738     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1739             String receiverPermission, Bundle options) {
1740         // pass
1741     }
1742 
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp)1743     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1744             String receiverPermission, int appOp) {
1745         // pass
1746     }
1747 
1748     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1749     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1750             String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
1751             int initialCode, String initialData, Bundle initialExtras) {
1752         // pass
1753     }
1754 
1755     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1756     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1757             String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
1758             Handler scheduler,
1759             int initialCode, String initialData, Bundle initialExtras) {
1760         // pass
1761     }
1762 
1763     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1764     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1765             String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
1766             Handler scheduler,
1767             int initialCode, String initialData, Bundle initialExtras) {
1768         // pass
1769     }
1770 
1771     @Override
sendStickyBroadcast(Intent arg0)1772     public void sendStickyBroadcast(Intent arg0) {
1773         // pass
1774 
1775     }
1776 
1777     @Override
sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1778     public void sendStickyOrderedBroadcast(Intent intent,
1779             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
1780            Bundle initialExtras) {
1781         // pass
1782     }
1783 
1784     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user)1785     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
1786         // pass
1787     }
1788 
1789     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options)1790     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
1791         // pass
1792     }
1793 
1794     @Override
sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1795     public void sendStickyOrderedBroadcastAsUser(Intent intent,
1796             UserHandle user, BroadcastReceiver resultReceiver,
1797             Handler scheduler, int initialCode, String initialData,
1798             Bundle initialExtras) {
1799         // pass
1800     }
1801 
1802     @Override
removeStickyBroadcastAsUser(Intent intent, UserHandle user)1803     public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
1804         // pass
1805     }
1806 
1807     @Override
setTheme(int arg0)1808     public void setTheme(int arg0) {
1809         // pass
1810 
1811     }
1812 
1813     @Override
setWallpaper(Bitmap arg0)1814     public void setWallpaper(Bitmap arg0) throws IOException {
1815         // pass
1816 
1817     }
1818 
1819     @Override
setWallpaper(InputStream arg0)1820     public void setWallpaper(InputStream arg0) throws IOException {
1821         // pass
1822 
1823     }
1824 
1825     @Override
startActivity(Intent arg0)1826     public void startActivity(Intent arg0) {
1827         // pass
1828     }
1829 
1830     @Override
startActivity(Intent arg0, Bundle arg1)1831     public void startActivity(Intent arg0, Bundle arg1) {
1832         // pass
1833     }
1834 
1835     @Override
startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)1836     public void startIntentSender(IntentSender intent,
1837             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
1838             throws IntentSender.SendIntentException {
1839         // pass
1840     }
1841 
1842     @Override
startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)1843     public void startIntentSender(IntentSender intent,
1844             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
1845             Bundle options) throws IntentSender.SendIntentException {
1846         // pass
1847     }
1848 
1849     @Override
startInstrumentation(ComponentName arg0, String arg1, Bundle arg2)1850     public boolean startInstrumentation(ComponentName arg0, String arg1,
1851             Bundle arg2) {
1852         // pass
1853         return false;
1854     }
1855 
1856     @Override
startService(Intent arg0)1857     public ComponentName startService(Intent arg0) {
1858         // pass
1859         return null;
1860     }
1861 
1862     @Override
startForegroundService(Intent service)1863     public ComponentName startForegroundService(Intent service) {
1864         // pass
1865         return null;
1866     }
1867 
1868     @Override
startForegroundServiceAsUser(Intent service, UserHandle user)1869     public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
1870         // pass
1871         return null;
1872     }
1873 
1874     @Override
stopService(Intent arg0)1875     public boolean stopService(Intent arg0) {
1876         // pass
1877         return false;
1878     }
1879 
1880     @Override
startServiceAsUser(Intent arg0, UserHandle arg1)1881     public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
1882         // pass
1883         return null;
1884     }
1885 
1886     @Override
stopServiceAsUser(Intent arg0, UserHandle arg1)1887     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
1888         // pass
1889         return false;
1890     }
1891 
1892     @Override
unbindService(ServiceConnection arg0)1893     public void unbindService(ServiceConnection arg0) {
1894         // pass
1895 
1896     }
1897 
1898     @Override
unregisterReceiver(BroadcastReceiver arg0)1899     public void unregisterReceiver(BroadcastReceiver arg0) {
1900         // pass
1901 
1902     }
1903 
1904     @Override
getApplicationContext()1905     public Context getApplicationContext() {
1906         return this;
1907     }
1908 
1909     @Override
startActivities(Intent[] arg0)1910     public void startActivities(Intent[] arg0) {
1911         // pass
1912 
1913     }
1914 
1915     @Override
startActivities(Intent[] arg0, Bundle arg1)1916     public void startActivities(Intent[] arg0, Bundle arg1) {
1917         // pass
1918 
1919     }
1920 
1921     @Override
isRestricted()1922     public boolean isRestricted() {
1923         return false;
1924     }
1925 
1926     @Override
getObbDir()1927     public File getObbDir() {
1928         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
1929         return null;
1930     }
1931 
1932     @Override
getDisplayAdjustments(int displayId)1933     public DisplayAdjustments getDisplayAdjustments(int displayId) {
1934         // pass
1935         return null;
1936     }
1937 
1938     @Override
getDisplay()1939     public Display getDisplay() {
1940         // pass
1941         return null;
1942     }
1943 
1944     @Override
updateDisplay(int displayId)1945     public void updateDisplay(int displayId) {
1946         // pass
1947     }
1948 
1949     @Override
getUserId()1950     public int getUserId() {
1951         return 0; // not used
1952     }
1953 
1954     @Override
getExternalFilesDirs(String type)1955     public File[] getExternalFilesDirs(String type) {
1956         // pass
1957         return new File[0];
1958     }
1959 
1960     @Override
getObbDirs()1961     public File[] getObbDirs() {
1962         // pass
1963         return new File[0];
1964     }
1965 
1966     @Override
getExternalCacheDirs()1967     public File[] getExternalCacheDirs() {
1968         // pass
1969         return new File[0];
1970     }
1971 
1972     @Override
getExternalMediaDirs()1973     public File[] getExternalMediaDirs() {
1974         // pass
1975         return new File[0];
1976     }
1977 
setScrollYPos(@onNull View view, int scrollPos)1978     public void setScrollYPos(@NonNull View view, int scrollPos) {
1979         mScrollYPos.put(view, scrollPos);
1980     }
1981 
getScrollYPos(@onNull View view)1982     public int getScrollYPos(@NonNull View view) {
1983         Integer pos = mScrollYPos.get(view);
1984         return pos != null ? pos : 0;
1985     }
1986 
setScrollXPos(@onNull View view, int scrollPos)1987     public void setScrollXPos(@NonNull View view, int scrollPos) {
1988         mScrollXPos.put(view, scrollPos);
1989     }
1990 
getScrollXPos(@onNull View view)1991     public int getScrollXPos(@NonNull View view) {
1992         Integer pos = mScrollXPos.get(view);
1993         return pos != null ? pos : 0;
1994     }
1995 
1996     @Override
createDeviceProtectedStorageContext()1997     public Context createDeviceProtectedStorageContext() {
1998         // pass
1999         return null;
2000     }
2001 
2002     @Override
createCredentialProtectedStorageContext()2003     public Context createCredentialProtectedStorageContext() {
2004         // pass
2005         return null;
2006     }
2007 
2008     @Override
isDeviceProtectedStorage()2009     public boolean isDeviceProtectedStorage() {
2010         return false;
2011     }
2012 
2013     @Override
isCredentialProtectedStorage()2014     public boolean isCredentialProtectedStorage() {
2015         return false;
2016     }
2017 
2018     @Override
canLoadUnsafeResources()2019     public boolean canLoadUnsafeResources() {
2020         return true;
2021     }
2022 
2023     private class AttributeHolder {
2024         private int resourceId;
2025         private String name;
2026         private boolean isFramework;
2027 
AttributeHolder(int resourceId, String name, boolean isFramework)2028         private AttributeHolder(int resourceId, String name, boolean isFramework) {
2029             this.resourceId = resourceId;
2030             this.name = name;
2031             this.isFramework = isFramework;
2032         }
2033     }
2034 
2035     /**
2036      * The cached value depends on
2037      * <ol>
2038      * <li>{@code int[]}: the attributes for which TypedArray is created </li>
2039      * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
2040      * creation of the TypedArray</li>
2041      * <li>{@code Integer}: the default style used at the time of creation</li>
2042      * </ol>
2043      *
2044      * The class is created by using nested maps resolving one dependency at a time.
2045      * <p/>
2046      * The final value of the nested maps is a pair of the typed array and a map of properties
2047      * that should be added to {@link #mDefaultPropMaps}, if needed.
2048      */
2049     private static class TypedArrayCache {
2050 
2051         private Map<int[],
2052                 Map<List<StyleResourceValue>,
2053                         Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
2054 
TypedArrayCache()2055         private TypedArrayCache() {
2056             mCache = new IdentityHashMap<>();
2057         }
2058 
get(int[] attrs, List<StyleResourceValue> themes, int resId)2059         public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
2060                 List<StyleResourceValue> themes, int resId) {
2061             Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
2062                     cacheFromThemes = mCache.get(attrs);
2063             if (cacheFromThemes != null) {
2064                 Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
2065                         cacheFromThemes.get(themes);
2066                 if (cacheFromResId != null) {
2067                     return cacheFromResId.get(resId);
2068                 }
2069             }
2070             return null;
2071         }
2072 
put(int[] attrs, List<StyleResourceValue> themes, int resId, Pair<BridgeTypedArray, PropertiesMap> value)2073         public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
2074                 Pair<BridgeTypedArray, PropertiesMap> value) {
2075             Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
2076                     cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>());
2077             Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
2078                     cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>());
2079             cacheFromResId.put(resId, value);
2080         }
2081 
2082     }
2083 }
2084