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