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