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