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.FileNotFoundException;
119 import java.io.FileOutputStream;
120 import java.io.IOException;
121 import java.io.InputStream;
122 import java.util.ArrayList;
123 import java.util.HashMap;
124 import java.util.IdentityHashMap;
125 import java.util.List;
126 import java.util.Map;
127 import java.util.concurrent.Executor;
128 
129 import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1;
130 
131 /**
132  * Custom implementation of Context/Activity to handle non compiled resources.
133  */
134 public class BridgeContext extends Context {
135     private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
136 
137     private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2);
138     private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3);
139     private static final int MAX_PARSER_STACK_SIZE = Integer.getInteger(
140             "layoutlib.max.parser.stack.size", 1000);
141 
142     static {
143         FRAMEWORK_PATCHED_VALUES.put("animateFirstView",
144                 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.BOOL,
145                         "animateFirstView", "false"));
146         FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges",
147                 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.BOOL,
148                         "animateLayoutChanges", "false"));
149 
150 
151         FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout",
152                 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.LAYOUT,
153                         "textEditSuggestionItemLayout", "text_edit_suggestion_item"));
154         FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout",
155                 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.LAYOUT,
156                         "textEditSuggestionContainerLayout", "text_edit_suggestion_container"));
157         FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle",
158                 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.STYLE,
159                         "textEditSuggestionHighlightStyle",
160                         "TextAppearance.Holo.SuggestionHighlight"));
161     }
162 
163     /** The map adds cookies to each view so that IDE can link xml tags to views. */
164     private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
165     /**
166      * In some cases, when inflating an xml, some objects are created. Then later, the objects are
167      * converted to views. This map stores the mapping from objects to cookies which can then be
168      * used to populate the mViewKeyMap.
169      */
170     private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
171     private final BridgeAssetManager mAssets;
172     private Resources mSystemResources;
173     private final Object mProjectKey;
174     private final DisplayMetrics mMetrics;
175     private final DynamicRenderResources mRenderResources;
176     private final Configuration mConfig;
177     private final ApplicationInfo mApplicationInfo;
178     private final LayoutlibCallback mLayoutlibCallback;
179     private final WindowManager mWindowManager;
180     private final DisplayManager mDisplayManager;
181     private AutofillManager mAutofillManager;
182     private final ClipboardManager mClipboardManager;
183     private final ActivityManager mActivityManager;
184     private final ConnectivityManager mConnectivityManager;
185     private final AudioManager mAudioManager;
186     private final InputManager mInputManager;
187     private final AppOpsManager mAppOpsManager;
188     private final UiModeManager mUiModeManager;
189     private final HashMap<View, Integer> mScrollYPos = new HashMap<>();
190     private final HashMap<View, Integer> mScrollXPos = new HashMap<>();
191 
192     private Resources.Theme mTheme;
193 
194     private final Map<Object, Map<ResourceReference, ResourceValue>> mDefaultPropMaps =
195             new IdentityHashMap<>();
196     private final Map<Object, ResourceReference> mDefaultStyleMap = new IdentityHashMap<>();
197 
198     // cache for TypedArray generated from StyleResourceValue object
199     private TypedArrayCache mTypedArrayCache;
200     private BridgeInflater mBridgeInflater;
201 
202     private BridgeContentResolver mContentResolver;
203 
204     private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
205     private SharedPreferences mSharedPreferences;
206     private ClassLoader mClassLoader;
207     private IBinder mBinder;
208     private PackageManager mPackageManager;
209     private Boolean mIsThemeAppCompat;
210     private boolean mUseThemedIcon;
211     private Context mApplicationContext;
212     private AccessibilityManager mAccessibilityManager;
213     private final ResourceNamespace mAppCompatNamespace;
214     private final Map<Key<?>, Object> mUserData = new HashMap<>();
215 
216     private final SessionInteractiveData mSessionInteractiveData;
217     private final ThreadLocal<AnimationHandler> mAnimationHandlerThreadLocal = new ThreadLocal<>();
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 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         BridgeXmlBlockParser parser = mParserStack.pop();
398         if (ParserFactory.LOG_PARSER) {
399             System.out.println("POPD " + parser.getParser().toString());
400         }
401     }
402 
403     /**
404      * Returns the current parser at the top the of the stack.
405      * @return a parser or null.
406      */
getCurrentParser()407     private BridgeXmlBlockParser getCurrentParser() {
408         return mParserStack.peek();
409     }
410 
411     /**
412      * Returns the previous parser.
413      * @return a parser or null if there isn't any previous parser
414      */
getPreviousParser()415     public BridgeXmlBlockParser getPreviousParser() {
416         if (mParserStack.size() < 2) {
417             return null;
418         }
419         return mParserStack.get(mParserStack.size() - 2);
420     }
421 
resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs)422     public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
423         ResourceReference resourceInfo = Bridge.resolveResourceId(resId);
424         if (resourceInfo == null) {
425             resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
426         }
427 
428         if (resourceInfo == null || resourceInfo.getResourceType() != ResourceType.ATTR) {
429             return false;
430         }
431 
432         ResourceValue value = mRenderResources.findItemInTheme(resourceInfo);
433         if (resolveRefs) {
434             value = mRenderResources.resolveResValue(value);
435         }
436 
437         if (value == null) {
438             // unable to find the attribute.
439             return false;
440         }
441 
442         // check if this is a style resource
443         if (value instanceof StyleResourceValue) {
444             // get the id that will represent this style.
445             outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value);
446             return true;
447         }
448 
449         String stringValue = value.getValue();
450         if (!stringValue.isEmpty()) {
451             if (stringValue.charAt(0) == '#') {
452                 outValue.data = ResourceHelper.getColor(stringValue);
453                 switch (stringValue.length()) {
454                     case 4:
455                         outValue.type = TypedValue.TYPE_INT_COLOR_RGB4;
456                         break;
457                     case 5:
458                         outValue.type = TypedValue.TYPE_INT_COLOR_ARGB4;
459                         break;
460                     case 7:
461                         outValue.type = TypedValue.TYPE_INT_COLOR_RGB8;
462                         break;
463                     default:
464                         outValue.type = TypedValue.TYPE_INT_COLOR_ARGB8;
465                 }
466             }
467             else if (stringValue.charAt(0) == '@') {
468                 outValue.type = TypedValue.TYPE_REFERENCE;
469             }
470             else if ("true".equals(stringValue) || "false".equals(stringValue)) {
471                 outValue.type = TypedValue.TYPE_INT_BOOLEAN;
472                 outValue.data = "true".equals(stringValue) ? 1 : 0;
473             }
474             else {
475                 try {
476                     outValue.data = Integer.parseInt(stringValue);
477                     outValue.type = TypedValue.TYPE_INT_DEC;
478                 }
479                 catch (NumberFormatException e) {
480                     if (!ResourceHelper.parseFloatAttribute(null, stringValue, outValue, false)) {
481                         outValue.type = TypedValue.TYPE_STRING;
482                         outValue.string = stringValue;
483                     }
484                 }
485             }
486         }
487 
488         int a = getResourceId(value.asReference(), 0 /*defValue*/);
489 
490         if (a != 0) {
491             outValue.resourceId = a;
492             return true;
493         }
494 
495         // If the value is not a valid reference, fallback to pass the value as a string.
496         outValue.string = stringValue;
497         return true;
498     }
499 
500 
resolveId(int id)501     public ResourceReference resolveId(int id) {
502         // first get the String related to this id in the framework
503         ResourceReference resourceInfo = Bridge.resolveResourceId(id);
504 
505         if (resourceInfo != null) {
506             return resourceInfo;
507         }
508 
509         // didn't find a match in the framework? look in the project.
510         if (mLayoutlibCallback != null) {
511             resourceInfo = mLayoutlibCallback.resolveResourceId(id);
512 
513             if (resourceInfo != null) {
514                 return resourceInfo;
515             }
516         }
517 
518         return null;
519     }
520 
inflateView(ResourceReference layout, ViewGroup parent, @SuppressWarnings("SameParameterValue") boolean attachToRoot, boolean skipCallbackParser)521     public Pair<View, Boolean> inflateView(ResourceReference layout, ViewGroup parent,
522             @SuppressWarnings("SameParameterValue") boolean attachToRoot,
523             boolean skipCallbackParser) {
524         boolean isPlatformLayout = layout.getNamespace().equals(ResourceNamespace.ANDROID);
525 
526         if (!isPlatformLayout && !skipCallbackParser) {
527             // check if the project callback can provide us with a custom parser.
528             ILayoutPullParser parser = null;
529             ResourceValue layoutValue = mRenderResources.getResolvedResource(layout);
530             if (layoutValue != null) {
531                 parser = getLayoutlibCallback().getParser(layoutValue);
532             }
533 
534             if (parser != null) {
535                 BridgeXmlBlockParser blockParser =
536                         new BridgeXmlBlockParser(parser, this, layout.getNamespace());
537                 try {
538                     pushParser(blockParser);
539                     return Pair.create(
540                             mBridgeInflater.inflate(blockParser, parent, attachToRoot),
541                             Boolean.TRUE);
542                 } finally {
543                     popParser();
544                 }
545             }
546         }
547 
548         ResourceValue resValue = mRenderResources.getResolvedResource(layout);
549 
550         if (resValue != null) {
551             String path = resValue.getValue();
552             // We need to create a pull parser around the layout XML file, and then
553             // give that to our XmlBlockParser.
554             try {
555                 XmlPullParser parser = ParserFactory.create(path, true);
556                 if (parser != null) {
557                     // Set the layout ref to have correct view cookies.
558                     mBridgeInflater.setResourceReference(layout);
559 
560                     BridgeXmlBlockParser blockParser =
561                             new BridgeXmlBlockParser(parser, this, layout.getNamespace());
562                     try {
563                         pushParser(blockParser);
564                         return Pair.create(mBridgeInflater.inflate(blockParser, parent,
565                                 attachToRoot),
566                                 Boolean.FALSE);
567                     } finally {
568                         popParser();
569                     }
570                 } else {
571                     Bridge.getLog().error(ILayoutLog.TAG_BROKEN,
572                             String.format("File %s is missing!", path), null, null);
573                 }
574             } catch (XmlPullParserException e) {
575                 Bridge.getLog().error(ILayoutLog.TAG_BROKEN,
576                         "Failed to parse file " + path, e, null, null /*data*/);
577                 // we'll return null below.
578             } finally {
579                 mBridgeInflater.setResourceReference(null);
580             }
581         } else {
582             Bridge.getLog().error(ILayoutLog.TAG_BROKEN,
583                     String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "",
584                             layout.getName()), null, null);
585         }
586 
587         return Pair.create(null, Boolean.FALSE);
588     }
589 
590     /**
591      * Returns whether the current selected theme is based on AppCompat
592      */
isAppCompatTheme()593     public boolean isAppCompatTheme() {
594         // If a cached value exists, return it.
595         if (mIsThemeAppCompat != null) {
596             return mIsThemeAppCompat;
597         }
598         // Ideally, we should check if the corresponding activity extends
599         // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
600         StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme();
601         // We can't simply check for parent using resources.themeIsParentOf() since the
602         // inheritance structure isn't really what one would expect. The first common parent
603         // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
604         boolean isThemeAppCompat = false;
605         for (int i = 0; i < 50; i++) {
606             if (defaultTheme == null) {
607                 break;
608             }
609             // for loop ensures that we don't run into cyclic theme inheritance.
610             if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) {
611                 isThemeAppCompat = true;
612                 break;
613             }
614             defaultTheme = mRenderResources.getParent(defaultTheme);
615         }
616         mIsThemeAppCompat = isThemeAppCompat;
617         return isThemeAppCompat;
618     }
619 
getAccessibilityManager()620     public AccessibilityManager getAccessibilityManager() {
621         if (mAccessibilityManager == null) {
622             mAccessibilityManager = new AccessibilityManager(this, null, UserHandle.USER_CURRENT);
623         }
624         return mAccessibilityManager;
625     }
626 
627     // ------------ Context methods
628 
629     @Override
getResources()630     public Resources getResources() {
631         return mSystemResources;
632     }
633 
634     @Override
getTheme()635     public Theme getTheme() {
636         return mTheme;
637     }
638 
639     @Override
getClassLoader()640     public ClassLoader getClassLoader() {
641         // The documentation for this method states that it should return a class loader one can
642         // use to retrieve classes in this package. However, when called by LayoutInflater, we do
643         // not want the class loader to return app's custom views.
644         // This is so that the IDE can instantiate the custom views and also generate proper error
645         // messages in case of failure. This also enables the IDE to fallback to MockView in case
646         // there's an exception thrown when trying to inflate the custom view.
647         // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to
648         // replace invocations of this method to a new method: getFrameworkClassLoader(). Also,
649         // the method is injected into Context. The implementation of getFrameworkClassLoader() is:
650         // "return getClass().getClassLoader();". This means that when LayoutInflater asks for
651         // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have
652         // access to the apps's custom views.
653         // This method can now return the right ClassLoader, which CustomViews can use to do the
654         // right thing.
655         if (mClassLoader == null) {
656             mClassLoader = new ClassLoader(getClass().getClassLoader()) {
657                 @Override
658                 protected Class<?> findClass(String name) throws ClassNotFoundException {
659                     for (String prefix : BridgeInflater.getClassPrefixList()) {
660                         if (name.startsWith(prefix)) {
661                             // These are framework classes and should not be loaded from the app.
662                             throw new ClassNotFoundException(name + " not found");
663                         }
664                     }
665                     return BridgeContext.this.mLayoutlibCallback.findClass(name);
666                 }
667             };
668         }
669         return mClassLoader;
670     }
671 
672     @Override
getSystemService(String service)673     public Object getSystemService(String service) {
674         switch (service) {
675             case LAYOUT_INFLATER_SERVICE:
676                 return mBridgeInflater;
677 
678             case TEXT_SERVICES_MANAGER_SERVICE:
679                 // we need to return a valid service to avoid NPE
680                 return TextServicesManager.getInstance();
681 
682             case WINDOW_SERVICE:
683                 return mWindowManager;
684 
685             case POWER_SERVICE:
686                 return new PowerManager(this, new BridgePowerManager(), new BridgeThermalService(),
687                         new Handler());
688 
689             case DISPLAY_SERVICE:
690                 return mDisplayManager;
691 
692             case ACCESSIBILITY_SERVICE:
693                 return AccessibilityManager.getInstance(this);
694 
695             case INPUT_METHOD_SERVICE:  // needed by SearchView and Compose
696                 return InputMethodManager.forContext(this);
697 
698             case AUTOFILL_MANAGER_SERVICE:
699                 if (mAutofillManager == null) {
700                     mAutofillManager = new AutofillManager(this, new Default());
701                 }
702                 return mAutofillManager;
703 
704             case CLIPBOARD_SERVICE:
705                 return mClipboardManager;
706 
707             case ACTIVITY_SERVICE:
708                 return mActivityManager;
709 
710             case CONNECTIVITY_SERVICE:
711                 return mConnectivityManager;
712 
713             case AUDIO_SERVICE:
714                 return mAudioManager;
715 
716             case INPUT_SERVICE:
717                 return mInputManager;
718 
719             case VIBRATOR_SERVICE:
720                 return NullVibrator.getInstance();
721 
722             case VIBRATOR_MANAGER_SERVICE:
723                 return NullVibratorManager.getInstance();
724 
725             case SENSOR_SERVICE:
726                 return EmptySensorManager.getInstance();
727 
728             case APP_OPS_SERVICE:
729                 return mAppOpsManager;
730 
731             case UI_MODE_SERVICE:
732                 return mUiModeManager;
733 
734             case TEXT_CLASSIFICATION_SERVICE:
735             case CONTENT_CAPTURE_MANAGER_SERVICE:
736             case ALARM_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         if (attributeList != null) {
948             for (int index = 0 ; index < attributeList.size() ; index++) {
949                 AttributeHolder attributeHolder = attributeList.get(index);
950 
951                 if (attributeHolder == null) {
952                     continue;
953                 }
954 
955                 String attrName = attributeHolder.getName();
956                 String value = null;
957                 if (set != null) {
958                     value = set.getAttributeValue(
959                             attributeHolder.getNamespace().getXmlNamespaceUri(), attrName);
960 
961                     // if this is an app attribute, and the first get fails, try with the
962                     // new res-auto namespace as well
963                     if (attributeHolder.getNamespace() != ResourceNamespace.ANDROID && value == null) {
964                         value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
965                     }
966                 }
967 
968                 // Calculate the default value from the Theme in two cases:
969                 //   - If defaultPropMap is not null, get the default value to add it to the list
970                 //   of default values of properties.
971                 //   - If value is null, it means that the attribute is not directly set as an
972                 //   attribute in the XML so try to get the default value.
973                 ResourceValue defaultValue = null;
974                 if (defaultPropMap != null || value == null) {
975                     // look for the value in the custom style first (and its parent if needed)
976                     ResourceReference attrRef = attributeHolder.asReference();
977                     if (customStyleValues != null) {
978                         defaultValue =
979                                 mRenderResources.findItemInStyle(customStyleValues, attrRef);
980                     }
981 
982                     // then look for the value in the default Style (and its parent if needed)
983                     if (defaultValue == null && defStyleValues != null) {
984                         defaultValue =
985                                 mRenderResources.findItemInStyle(defStyleValues, attrRef);
986                     }
987 
988                     // if the item is not present in the defStyle, we look in the main theme (and
989                     // its parent themes)
990                     if (defaultValue == null) {
991                         defaultValue =
992                                 mRenderResources.findItemInTheme(attrRef);
993                     }
994 
995                     // if we found a value, we make sure this doesn't reference another value.
996                     // So we resolve it.
997                     if (defaultValue != null) {
998                         if (defaultPropMap != null) {
999                             defaultPropMap.put(attrRef, defaultValue);
1000                         }
1001 
1002                         defaultValue = mRenderResources.resolveResValue(defaultValue);
1003                     }
1004                 }
1005                 // Done calculating the defaultValue.
1006 
1007                 // If there's no direct value for this attribute in the XML, we look for default
1008                 // values in the widget defStyle, and then in the theme.
1009                 if (value == null) {
1010                     if (attributeHolder.getNamespace() == ResourceNamespace.ANDROID) {
1011                         // For some framework values, layoutlib patches the actual value in the
1012                         // theme when it helps to improve the final preview. In most cases
1013                         // we just disable animations.
1014                         ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName);
1015                         if (patchedValue != null) {
1016                             defaultValue = patchedValue;
1017                         }
1018                     }
1019 
1020                     // If we found a value, we make sure this doesn't reference another value.
1021                     // So we resolve it.
1022                     if (defaultValue != null) {
1023                         // If the value is a reference to another theme attribute that doesn't
1024                         // exist, we should log a warning and omit it.
1025                         String val = defaultValue.getValue();
1026                         if (val != null && val.startsWith(AndroidConstants.PREFIX_THEME_REF)) {
1027                             // Because we always use the latest framework code, some resources might
1028                             // fail to resolve when using old themes (they haven't been backported).
1029                             // Since this is an artifact caused by us using always the latest
1030                             // code, we check for some of those values and replace them here.
1031                             ResourceReference reference = defaultValue.getReference();
1032                             defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName);
1033 
1034                             // Only log a warning if the referenced value isn't one of the RTL
1035                             // attributes, or the app targets old API.
1036                             if (defaultValue == null &&
1037                                     (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 ||
1038                                     !attrName.equals(RTL_ATTRS.get(val)))) {
1039                                 if (reference != null) {
1040                                     val = reference.getResourceUrl().toString();
1041                                 }
1042                                 Bridge.getLog().warning(ILayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
1043                                         String.format("Failed to find '%s' in current theme.", val),
1044                                         null, val);
1045                             }
1046                         }
1047                     }
1048 
1049                     ta.bridgeSetValue(
1050                             index,
1051                             attrName, attributeHolder.getNamespace(),
1052                             attributeHolder.getResourceId(),
1053                             defaultValue);
1054                 } else {
1055                     // There is a value in the XML, but we need to resolve it in case it's
1056                     // referencing another resource or a theme value.
1057                     ta.bridgeSetValue(
1058                             index,
1059                             attrName, attributeHolder.getNamespace(),
1060                             attributeHolder.getResourceId(),
1061                             mRenderResources.resolveResValue(
1062                                     new UnresolvedResourceValue(
1063                                             value, currentFileNamespace, resolver)));
1064                 }
1065             }
1066         }
1067 
1068         ta.sealArray();
1069 
1070         return ta;
1071     }
1072 
1073     @Override
getMainLooper()1074     public Looper getMainLooper() {
1075         return Looper.myLooper();
1076     }
1077 
1078 
1079     @Override
getPackageName()1080     public String getPackageName() {
1081         if (mApplicationInfo.packageName == null) {
1082             mApplicationInfo.packageName = mLayoutlibCallback.getApplicationId();
1083         }
1084         return mApplicationInfo.packageName;
1085     }
1086 
1087     @Override
getPackageManager()1088     public PackageManager getPackageManager() {
1089         if (mPackageManager == null) {
1090             mPackageManager = new BridgePackageManager(this);
1091         }
1092         return mPackageManager;
1093     }
1094 
1095     @Override
registerComponentCallbacks(ComponentCallbacks callback)1096     public void registerComponentCallbacks(ComponentCallbacks callback) {}
1097 
1098     @Override
unregisterComponentCallbacks(ComponentCallbacks callback)1099     public void unregisterComponentCallbacks(ComponentCallbacks callback) {}
1100 
1101     // ------------- private new methods
1102 
1103     /**
1104      * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
1105      * values found in the given style. If no style is specified, the default theme, along with the
1106      * styles applied to it are used.
1107      *
1108      * @see #obtainStyledAttributes(int, int[])
1109      */
createStyleBasedTypedArray( @ullable StyleResourceValue style, int[] attrs)1110     private Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> createStyleBasedTypedArray(
1111             @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
1112         List<AttributeHolder> attributes = searchAttrs(attrs);
1113 
1114         BridgeTypedArray ta =
1115                 Resources_Delegate.newTypeArray(mSystemResources, attrs.length);
1116 
1117         Map<ResourceReference, ResourceValue> defaultPropMap = new HashMap<>();
1118         // for each attribute, get its name so that we can search it in the style
1119         for (int i = 0; i < attrs.length; i++) {
1120             AttributeHolder attrHolder = attributes.get(i);
1121 
1122             if (attrHolder != null) {
1123                 // look for the value in the given style
1124                 ResourceValue resValue;
1125                 if (style != null) {
1126                     resValue = mRenderResources.findItemInStyle(style, attrHolder.asReference());
1127                 } else {
1128                     resValue = mRenderResources.findItemInTheme(attrHolder.asReference());
1129                 }
1130 
1131                 if (resValue != null) {
1132                     defaultPropMap.put(attrHolder.asReference(), resValue);
1133                     // resolve it to make sure there are no references left.
1134                     resValue = mRenderResources.resolveResValue(resValue);
1135                     ta.bridgeSetValue(
1136                             i, attrHolder.getName(), attrHolder.getNamespace(),
1137                             attrHolder.getResourceId(),
1138                             resValue);
1139                 }
1140             }
1141         }
1142 
1143         ta.sealArray();
1144 
1145         return Pair.create(ta, defaultPropMap);
1146     }
1147 
1148     /**
1149      * The input int[] attributeIds is a list of attributes. The returns a list of information about
1150      * each attributes. The information is (name, isFramework)
1151      * <p/>
1152      *
1153      * @param attributeIds An attribute array reference given to obtainStyledAttributes.
1154      * @return List of attribute information.
1155      */
searchAttrs(int[] attributeIds)1156     private List<AttributeHolder> searchAttrs(int[] attributeIds) {
1157         List<AttributeHolder> results = new ArrayList<>(attributeIds.length);
1158 
1159         // for each attribute, get its name so that we can search it in the style
1160         for (int id : attributeIds) {
1161             ResourceReference refForId = Bridge.resolveResourceId(id);
1162             if (refForId == null) {
1163                 refForId = mLayoutlibCallback.resolveResourceId(id);
1164             }
1165 
1166             if (refForId != null) {
1167                 results.add(new AttributeHolder(id, refForId));
1168             } else {
1169                 results.add(null);
1170             }
1171         }
1172 
1173         return results;
1174     }
1175 
1176     /**
1177      * Searches for the attribute referenced by its internal id.
1178      */
searchAttr(int attrId)1179     private ResourceReference searchAttr(int attrId) {
1180         ResourceReference attr = Bridge.resolveResourceId(attrId);
1181         if (attr == null) {
1182             attr = mLayoutlibCallback.resolveResourceId(attrId);
1183         }
1184 
1185         return attr;
1186     }
1187 
1188     /**
1189      * Maps a given style to a numeric id.
1190      *
1191      * <p>For now Bridge handles numeric ids (both fixed and dynamic) for framework and the callback
1192      * for non-framework. TODO(b/156609434): teach the IDE about fixed framework ids and handle this
1193      * all in the callback.
1194      */
getDynamicIdByStyle(StyleResourceValue resValue)1195     public int getDynamicIdByStyle(StyleResourceValue resValue) {
1196         if (resValue.isFramework()) {
1197             return Bridge.getResourceId(resValue.getResourceType(), resValue.getName());
1198         } else {
1199             return mLayoutlibCallback.getOrGenerateResourceId(resValue.asReference());
1200         }
1201     }
1202 
1203     /**
1204      * Maps a numeric id back to {@link StyleResourceValue}.
1205      *
1206      * <p>For now framework numeric ids are handled by Bridge, so try there first and fall back to
1207      * the callback, which manages ids for non-framework resources. TODO(b/156609434): manage all
1208      * ids in the IDE.
1209      *
1210      * <p>Once we the resource for the given id, we ask the IDE to get the
1211      * {@link StyleResourceValue} for it.
1212      */
1213     @Nullable
getStyleByDynamicId(int id)1214     private StyleResourceValue getStyleByDynamicId(int id) {
1215         ResourceReference reference = Bridge.resolveResourceId(id);
1216         if (reference == null) {
1217             reference = mLayoutlibCallback.resolveResourceId(id);
1218         }
1219 
1220         if (reference == null) {
1221             return null;
1222         }
1223 
1224         return mRenderResources.getStyle(reference);
1225     }
1226 
getResourceId(@onNull ResourceReference resource, int defValue)1227     public int getResourceId(@NonNull ResourceReference resource, int defValue) {
1228         if (getRenderResources().getUnresolvedResource(resource) != null) {
1229             if (resource.getNamespace().equals(ResourceNamespace.ANDROID)) {
1230                 return Bridge.getResourceId(resource.getResourceType(), resource.getName());
1231             } else if (mLayoutlibCallback != null) {
1232                 return mLayoutlibCallback.getOrGenerateResourceId(resource);
1233             }
1234         }
1235 
1236         return defValue;
1237     }
1238 
getBaseContext(Context context)1239     public static Context getBaseContext(Context context) {
1240         while (context instanceof ContextWrapper) {
1241             context = ((ContextWrapper) context).getBaseContext();
1242         }
1243         return context;
1244     }
1245 
1246     /**
1247      * Returns the Framework attr resource reference with the given name.
1248      */
1249     @NonNull
createFrameworkAttrReference(@onNull String name)1250     public static ResourceReference createFrameworkAttrReference(@NonNull String name) {
1251         return createFrameworkResourceReference(ResourceType.ATTR, name);
1252     }
1253 
1254     /**
1255      * Returns the Framework resource reference with the given type and name.
1256      */
1257     @NonNull
createFrameworkResourceReference(@onNull ResourceType type, @NonNull String name)1258     public static ResourceReference createFrameworkResourceReference(@NonNull ResourceType type,
1259             @NonNull String name) {
1260         return new ResourceReference(ResourceNamespace.ANDROID, type, name);
1261     }
1262 
1263     /**
1264      * Returns the AppCompat attr resource reference with the given name.
1265      */
1266     @NonNull
createAppCompatAttrReference(@onNull String name)1267     public ResourceReference createAppCompatAttrReference(@NonNull String name) {
1268         return createAppCompatResourceReference(ResourceType.ATTR, name);
1269     }
1270 
1271     /**
1272      * Returns the AppCompat resource reference with the given type and name.
1273      */
1274     @NonNull
createAppCompatResourceReference(@onNull ResourceType type, @NonNull String name)1275     public ResourceReference createAppCompatResourceReference(@NonNull ResourceType type,
1276             @NonNull String name) {
1277         return new ResourceReference(mAppCompatNamespace, type, name);
1278     }
1279 
getBinder()1280     public IBinder getBinder() {
1281         if (mBinder == null) {
1282             // create a no-op binder. We only need it be not null.
1283             mBinder = new IBinder() {
1284                 @Override
1285                 public String getInterfaceDescriptor() throws RemoteException {
1286                     return null;
1287                 }
1288 
1289                 @Override
1290                 public boolean pingBinder() {
1291                     return false;
1292                 }
1293 
1294                 @Override
1295                 public boolean isBinderAlive() {
1296                     return false;
1297                 }
1298 
1299                 @Override
1300                 public IInterface queryLocalInterface(String descriptor) {
1301                     return null;
1302                 }
1303 
1304                 @Override
1305                 public void dump(FileDescriptor fd, String[] args) throws RemoteException {
1306 
1307                 }
1308 
1309                 @Override
1310                 public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
1311 
1312                 }
1313 
1314                 @Override
1315                 public boolean transact(int code, Parcel data, Parcel reply, int flags)
1316                         throws RemoteException {
1317                     return false;
1318                 }
1319 
1320                 @Override
1321                 public void linkToDeath(DeathRecipient recipient, int flags)
1322                         throws RemoteException {
1323 
1324                 }
1325 
1326                 @Override
1327                 public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
1328                     return false;
1329                 }
1330 
1331                 @Override
1332                 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1333                   String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) {
1334                 }
1335             };
1336         }
1337         return mBinder;
1338     }
1339 
1340     //------------ NOT OVERRIDEN --------------------
1341 
1342     @Override
bindService(Intent arg0, ServiceConnection arg1, int arg2)1343     public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
1344         // pass
1345         return false;
1346     }
1347 
1348     @Override
bindService(Intent arg0, int arg1, Executor arg2, ServiceConnection arg3)1349     public boolean bindService(Intent arg0, int arg1, Executor arg2, ServiceConnection arg3) {
1350         return false;
1351     }
1352 
1353     @Override
bindIsolatedService(Intent arg0, int arg1, String arg2, Executor arg3, ServiceConnection arg4)1354     public boolean bindIsolatedService(Intent arg0,
1355             int arg1, String arg2, Executor arg3, ServiceConnection arg4) {
1356         return false;
1357     }
1358 
1359     @Override
checkCallingOrSelfPermission(String arg0)1360     public int checkCallingOrSelfPermission(String arg0) {
1361         // pass
1362         return 0;
1363     }
1364 
1365     @Override
checkCallingOrSelfUriPermission(Uri arg0, int arg1)1366     public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
1367         // pass
1368         return 0;
1369     }
1370 
1371     @Override
checkCallingPermission(String arg0)1372     public int checkCallingPermission(String arg0) {
1373         // pass
1374         return 0;
1375     }
1376 
1377     @Override
checkCallingUriPermission(Uri arg0, int arg1)1378     public int checkCallingUriPermission(Uri arg0, int arg1) {
1379         // pass
1380         return 0;
1381     }
1382 
1383     @Override
checkPermission(String arg0, int arg1, int arg2)1384     public int checkPermission(String arg0, int arg1, int arg2) {
1385         // pass
1386         return 0;
1387     }
1388 
1389     @Override
checkSelfPermission(String arg0)1390     public int checkSelfPermission(String arg0) {
1391         // pass
1392         return 0;
1393     }
1394 
1395     @Override
checkPermission(String arg0, int arg1, int arg2, IBinder arg3)1396     public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
1397         // pass
1398         return 0;
1399     }
1400 
1401     @Override
checkUriPermission(Uri arg0, int arg1, int arg2, int arg3)1402     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
1403         // pass
1404         return 0;
1405     }
1406 
1407     @Override
checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4)1408     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) {
1409         // pass
1410         return 0;
1411     }
1412 
1413     @Override
checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5)1414     public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
1415             int arg4, int arg5) {
1416         // pass
1417         return 0;
1418     }
1419 
1420     @Override
clearWallpaper()1421     public void clearWallpaper() {
1422         // pass
1423 
1424     }
1425 
1426     @Override
createPackageContext(String arg0, int arg1)1427     public Context createPackageContext(String arg0, int arg1) {
1428         // pass
1429         return null;
1430     }
1431 
1432     @Override
createPackageContextAsUser(String arg0, int arg1, UserHandle user)1433     public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
1434         // pass
1435         return null;
1436     }
1437 
1438     @Override
createConfigurationContext(Configuration overrideConfiguration)1439     public Context createConfigurationContext(Configuration overrideConfiguration) {
1440         // pass
1441         return null;
1442     }
1443 
1444     @Override
createDisplayContext(Display display)1445     public Context createDisplayContext(Display display) {
1446         // pass
1447         return null;
1448     }
1449 
1450     @Override
createContextForSplit(String splitName)1451     public Context createContextForSplit(String splitName) {
1452         // pass
1453         return null;
1454     }
1455 
1456     @Override
databaseList()1457     public String[] databaseList() {
1458         // pass
1459         return null;
1460     }
1461 
1462     @Override
createApplicationContext(ApplicationInfo application, int flags)1463     public Context createApplicationContext(ApplicationInfo application, int flags)
1464             throws PackageManager.NameNotFoundException {
1465         return null;
1466     }
1467 
1468     @Override
moveDatabaseFrom(Context sourceContext, String name)1469     public boolean moveDatabaseFrom(Context sourceContext, String name) {
1470         // pass
1471         return false;
1472     }
1473 
1474     @Override
deleteDatabase(String arg0)1475     public boolean deleteDatabase(String arg0) {
1476         // pass
1477         return false;
1478     }
1479 
1480     @Override
deleteFile(String arg0)1481     public boolean deleteFile(String arg0) {
1482         // pass
1483         return false;
1484     }
1485 
1486     @Override
enforceCallingOrSelfPermission(String arg0, String arg1)1487     public void enforceCallingOrSelfPermission(String arg0, String arg1) {
1488         // pass
1489 
1490     }
1491 
1492     @Override
enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2)1493     public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
1494             String arg2) {
1495         // pass
1496 
1497     }
1498 
1499     @Override
enforceCallingPermission(String arg0, String arg1)1500     public void enforceCallingPermission(String arg0, String arg1) {
1501         // pass
1502 
1503     }
1504 
1505     @Override
enforceCallingUriPermission(Uri arg0, int arg1, String arg2)1506     public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
1507         // pass
1508 
1509     }
1510 
1511     @Override
enforcePermission(String arg0, int arg1, int arg2, String arg3)1512     public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
1513         // pass
1514 
1515     }
1516 
1517     @Override
enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4)1518     public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
1519             String arg4) {
1520         // pass
1521 
1522     }
1523 
1524     @Override
enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6)1525     public void enforceUriPermission(Uri arg0, String arg1, String arg2,
1526             int arg3, int arg4, int arg5, String arg6) {
1527         // pass
1528 
1529     }
1530 
1531     @Override
fileList()1532     public String[] fileList() {
1533         // pass
1534         return null;
1535     }
1536 
1537     @Override
getAssets()1538     public BridgeAssetManager getAssets() {
1539         return mAssets;
1540     }
1541 
1542     @Override
getCacheDir()1543     public File getCacheDir() {
1544         // pass
1545         return null;
1546     }
1547 
1548     @Override
getCodeCacheDir()1549     public File getCodeCacheDir() {
1550         // pass
1551         return null;
1552     }
1553 
1554     @Override
getExternalCacheDir()1555     public File getExternalCacheDir() {
1556         // pass
1557         return null;
1558     }
1559 
1560     @Override
getPreloadsFileCache()1561     public File getPreloadsFileCache() {
1562         // pass
1563         return null;
1564     }
1565 
1566     @Override
getContentResolver()1567     public ContentResolver getContentResolver() {
1568         if (mContentResolver == null) {
1569             mContentResolver = new BridgeContentResolver(getApplicationContext());
1570         }
1571         return mContentResolver;
1572     }
1573 
1574     @Override
getDatabasePath(String arg0)1575     public File getDatabasePath(String arg0) {
1576         // pass
1577         return null;
1578     }
1579 
1580     @Override
getDir(String arg0, int arg1)1581     public File getDir(String arg0, int arg1) {
1582         // pass
1583         return null;
1584     }
1585 
1586     @Override
getFileStreamPath(String arg0)1587     public File getFileStreamPath(String arg0) {
1588         // pass
1589         return null;
1590     }
1591 
1592     @Override
getSharedPreferencesPath(String name)1593     public File getSharedPreferencesPath(String name) {
1594         // pass
1595         return null;
1596     }
1597 
1598     @Override
getDataDir()1599     public File getDataDir() {
1600         // pass
1601         return null;
1602     }
1603 
1604     @Override
getFilesDir()1605     public File getFilesDir() {
1606         // pass
1607         return null;
1608     }
1609 
1610     @Override
getNoBackupFilesDir()1611     public File getNoBackupFilesDir() {
1612         // pass
1613         return null;
1614     }
1615 
1616     @Override
getExternalFilesDir(String type)1617     public File getExternalFilesDir(String type) {
1618         // pass
1619         return null;
1620     }
1621 
1622     @Override
getPackageCodePath()1623     public String getPackageCodePath() {
1624         // pass
1625         return null;
1626     }
1627 
1628     @Override
getBasePackageName()1629     public String getBasePackageName() {
1630         // pass
1631         return null;
1632     }
1633 
1634     @Override
getOpPackageName()1635     public String getOpPackageName() {
1636         // pass
1637         return null;
1638     }
1639 
1640     @Override
getApplicationInfo()1641     public ApplicationInfo getApplicationInfo() {
1642         return mApplicationInfo;
1643     }
1644 
1645     @Override
getPackageResourcePath()1646     public String getPackageResourcePath() {
1647         // pass
1648         return null;
1649     }
1650 
1651     @Override
getSharedPreferences(String arg0, int arg1)1652     public SharedPreferences getSharedPreferences(String arg0, int arg1) {
1653         if (mSharedPreferences == null) {
1654             mSharedPreferences = new BridgeSharedPreferences();
1655         }
1656         return mSharedPreferences;
1657     }
1658 
1659     @Override
getSharedPreferences(File arg0, int arg1)1660     public SharedPreferences getSharedPreferences(File arg0, int arg1) {
1661         if (mSharedPreferences == null) {
1662             mSharedPreferences = new BridgeSharedPreferences();
1663         }
1664         return mSharedPreferences;
1665     }
1666 
1667     @Override
reloadSharedPreferences()1668     public void reloadSharedPreferences() {
1669         // intentional noop
1670     }
1671 
1672     @Override
moveSharedPreferencesFrom(Context sourceContext, String name)1673     public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
1674         // pass
1675         return false;
1676     }
1677 
1678     @Override
deleteSharedPreferences(String name)1679     public boolean deleteSharedPreferences(String name) {
1680         // pass
1681         return false;
1682     }
1683 
1684     @Override
getWallpaper()1685     public Drawable getWallpaper() {
1686         // pass
1687         return null;
1688     }
1689 
1690     @Override
getWallpaperDesiredMinimumWidth()1691     public int getWallpaperDesiredMinimumWidth() {
1692         return -1;
1693     }
1694 
1695     @Override
getWallpaperDesiredMinimumHeight()1696     public int getWallpaperDesiredMinimumHeight() {
1697         return -1;
1698     }
1699 
1700     @Override
grantUriPermission(String arg0, Uri arg1, int arg2)1701     public void grantUriPermission(String arg0, Uri arg1, int arg2) {
1702         // pass
1703 
1704     }
1705 
1706     @Override
openFileInput(String arg0)1707     public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
1708         // pass
1709         return null;
1710     }
1711 
1712     @Override
openFileOutput(String arg0, int arg1)1713     public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
1714         // pass
1715         return null;
1716     }
1717 
1718     @Override
openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2)1719     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
1720         // pass
1721         return null;
1722     }
1723 
1724     @Override
openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2, DatabaseErrorHandler arg3)1725     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
1726             CursorFactory arg2, DatabaseErrorHandler arg3) {
1727         // pass
1728         return null;
1729     }
1730 
1731     @Override
peekWallpaper()1732     public Drawable peekWallpaper() {
1733         // pass
1734         return null;
1735     }
1736 
1737     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1)1738     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
1739         // pass
1740         return null;
1741     }
1742 
1743     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2)1744     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2) {
1745         // pass
1746         return null;
1747     }
1748 
1749     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3)1750     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
1751             String arg2, Handler arg3) {
1752         // pass
1753         return null;
1754     }
1755 
1756     @Override
registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3, int arg4)1757     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
1758             String arg2, Handler arg3, int arg4) {
1759         // pass
1760         return null;
1761     }
1762 
1763     @Override
registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3)1764     public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
1765             IntentFilter arg1, String arg2, Handler arg3) {
1766         // pass
1767         return null;
1768     }
1769 
1770     @Override
registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3, int arg4)1771     public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
1772             IntentFilter arg1, String arg2, Handler arg3, int arg4) {
1773         // pass
1774         return null;
1775     }
1776 
1777     @Override
removeStickyBroadcast(Intent arg0)1778     public void removeStickyBroadcast(Intent arg0) {
1779         // pass
1780 
1781     }
1782 
1783     @Override
revokeUriPermission(Uri arg0, int arg1)1784     public void revokeUriPermission(Uri arg0, int arg1) {
1785         // pass
1786 
1787     }
1788 
1789     @Override
revokeUriPermission(String arg0, Uri arg1, int arg2)1790     public void revokeUriPermission(String arg0, Uri arg1, int arg2) {
1791         // pass
1792 
1793     }
1794 
1795     @Override
sendBroadcast(Intent arg0)1796     public void sendBroadcast(Intent arg0) {
1797         // pass
1798 
1799     }
1800 
1801     @Override
sendBroadcast(Intent arg0, String arg1)1802     public void sendBroadcast(Intent arg0, String arg1) {
1803         // pass
1804 
1805     }
1806 
1807     @Override
sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)1808     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
1809         // pass
1810 
1811     }
1812 
1813     @Override
sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions)1814     public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
1815             String[] receiverPermissions) {
1816         // pass
1817 
1818     }
1819 
1820     @Override
sendBroadcast(Intent arg0, String arg1, Bundle arg2)1821     public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) {
1822         // pass
1823 
1824     }
1825 
1826     @Override
sendBroadcast(Intent intent, String receiverPermission, int appOp)1827     public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
1828         // pass
1829     }
1830 
1831     @Override
sendOrderedBroadcast(Intent arg0, String arg1)1832     public void sendOrderedBroadcast(Intent arg0, String arg1) {
1833         // pass
1834 
1835     }
1836 
1837     @Override
sendOrderedBroadcast(Intent arg0, String arg1, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1838     public void sendOrderedBroadcast(Intent arg0, String arg1,
1839             BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
1840             Bundle arg6) {
1841         // pass
1842 
1843     }
1844 
1845     @Override
sendOrderedBroadcast(Intent arg0, String arg1, Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1846     public void sendOrderedBroadcast(Intent arg0, String arg1,
1847             Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
1848             Bundle arg6) {
1849         // pass
1850 
1851     }
1852 
1853     @Override
sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1854     public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
1855             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
1856             String initialData, Bundle initialExtras) {
1857         // pass
1858     }
1859 
1860     @Override
sendBroadcastAsUser(Intent intent, UserHandle user)1861     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
1862         // pass
1863     }
1864 
1865     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)1866     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1867             String receiverPermission) {
1868         // pass
1869     }
1870 
1871     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options)1872     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1873             String receiverPermission, Bundle options) {
1874         // pass
1875     }
1876 
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp)1877     public void sendBroadcastAsUser(Intent intent, UserHandle user,
1878             String receiverPermission, int appOp) {
1879         // pass
1880     }
1881 
1882     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1883     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1884             String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
1885             int initialCode, String initialData, Bundle initialExtras) {
1886         // pass
1887     }
1888 
1889     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1890     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1891             String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
1892             Handler scheduler,
1893             int initialCode, String initialData, Bundle initialExtras) {
1894         // pass
1895     }
1896 
1897     @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1898     public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1899             String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
1900             Handler scheduler,
1901             int initialCode, String initialData, Bundle initialExtras) {
1902         // pass
1903     }
1904 
1905     @Override
sendStickyBroadcast(Intent arg0)1906     public void sendStickyBroadcast(Intent arg0) {
1907         // pass
1908 
1909     }
1910 
1911     @Override
sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1912     public void sendStickyOrderedBroadcast(Intent intent,
1913             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
1914            Bundle initialExtras) {
1915         // pass
1916     }
1917 
1918     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user)1919     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
1920         // pass
1921     }
1922 
1923     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options)1924     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
1925         // pass
1926     }
1927 
1928     @Override
sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1929     public void sendStickyOrderedBroadcastAsUser(Intent intent,
1930             UserHandle user, BroadcastReceiver resultReceiver,
1931             Handler scheduler, int initialCode, String initialData,
1932             Bundle initialExtras) {
1933         // pass
1934     }
1935 
1936     @Override
removeStickyBroadcastAsUser(Intent intent, UserHandle user)1937     public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
1938         // pass
1939     }
1940 
1941     @Override
setTheme(int arg0)1942     public void setTheme(int arg0) {
1943         // pass
1944 
1945     }
1946 
1947     @Override
setWallpaper(Bitmap arg0)1948     public void setWallpaper(Bitmap arg0) throws IOException {
1949         // pass
1950 
1951     }
1952 
1953     @Override
setWallpaper(InputStream arg0)1954     public void setWallpaper(InputStream arg0) throws IOException {
1955         // pass
1956 
1957     }
1958 
1959     @Override
startActivity(Intent arg0)1960     public void startActivity(Intent arg0) {
1961         // pass
1962     }
1963 
1964     @Override
startActivity(Intent arg0, Bundle arg1)1965     public void startActivity(Intent arg0, Bundle arg1) {
1966         // pass
1967     }
1968 
1969     @Override
startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)1970     public void startIntentSender(IntentSender intent,
1971             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
1972             throws IntentSender.SendIntentException {
1973         // pass
1974     }
1975 
1976     @Override
startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)1977     public void startIntentSender(IntentSender intent,
1978             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
1979             Bundle options) throws IntentSender.SendIntentException {
1980         // pass
1981     }
1982 
1983     @Override
startInstrumentation(ComponentName arg0, String arg1, Bundle arg2)1984     public boolean startInstrumentation(ComponentName arg0, String arg1,
1985             Bundle arg2) {
1986         // pass
1987         return false;
1988     }
1989 
1990     @Override
startService(Intent arg0)1991     public ComponentName startService(Intent arg0) {
1992         // pass
1993         return null;
1994     }
1995 
1996     @Override
startForegroundService(Intent service)1997     public ComponentName startForegroundService(Intent service) {
1998         // pass
1999         return null;
2000     }
2001 
2002     @Override
startForegroundServiceAsUser(Intent service, UserHandle user)2003     public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
2004         // pass
2005         return null;
2006     }
2007 
2008     @Override
stopService(Intent arg0)2009     public boolean stopService(Intent arg0) {
2010         // pass
2011         return false;
2012     }
2013 
2014     @Override
startServiceAsUser(Intent arg0, UserHandle arg1)2015     public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
2016         // pass
2017         return null;
2018     }
2019 
2020     @Override
stopServiceAsUser(Intent arg0, UserHandle arg1)2021     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
2022         // pass
2023         return false;
2024     }
2025 
2026     @Override
updateServiceGroup(@onNull ServiceConnection conn, int group, int importance)2027     public void updateServiceGroup(@NonNull ServiceConnection conn, int group,
2028             int importance) {
2029         // pass
2030     }
2031 
2032     @Override
unbindService(ServiceConnection arg0)2033     public void unbindService(ServiceConnection arg0) {
2034         // pass
2035 
2036     }
2037 
2038     @Override
unregisterReceiver(BroadcastReceiver arg0)2039     public void unregisterReceiver(BroadcastReceiver arg0) {
2040         // pass
2041 
2042     }
2043 
2044     @Override
getApplicationContext()2045     public Context getApplicationContext() {
2046         if (mApplicationContext == null) {
2047             mApplicationContext = new ApplicationContext(this);
2048         }
2049         return mApplicationContext;
2050     }
2051 
2052     @Override
startActivities(Intent[] arg0)2053     public void startActivities(Intent[] arg0) {
2054         // pass
2055 
2056     }
2057 
2058     @Override
startActivities(Intent[] arg0, Bundle arg1)2059     public void startActivities(Intent[] arg0, Bundle arg1) {
2060         // pass
2061 
2062     }
2063 
2064     @Override
isRestricted()2065     public boolean isRestricted() {
2066         return false;
2067     }
2068 
2069     @Override
getObbDir()2070     public File getObbDir() {
2071         Bridge.getLog().error(ILayoutLog.TAG_UNSUPPORTED, "OBB not supported", null, null);
2072         return null;
2073     }
2074 
2075     @Override
getDisplayAdjustments(int displayId)2076     public DisplayAdjustments getDisplayAdjustments(int displayId) {
2077         // pass
2078         return null;
2079     }
2080 
2081     @Override
getDisplay()2082     public Display getDisplay() {
2083         // pass
2084         return null;
2085     }
2086 
2087     @Override
getDisplayId()2088     public int getDisplayId() {
2089         // pass
2090         return 0;
2091     }
2092 
2093     @Override
updateDisplay(int displayId)2094     public void updateDisplay(int displayId) {
2095         // pass
2096     }
2097 
2098     @Override
getUserId()2099     public int getUserId() {
2100         return 0; // not used
2101     }
2102 
2103     @Override
getExternalFilesDirs(String type)2104     public File[] getExternalFilesDirs(String type) {
2105         // pass
2106         return new File[0];
2107     }
2108 
2109     @Override
getObbDirs()2110     public File[] getObbDirs() {
2111         // pass
2112         return new File[0];
2113     }
2114 
2115     @Override
getExternalCacheDirs()2116     public File[] getExternalCacheDirs() {
2117         // pass
2118         return new File[0];
2119     }
2120 
2121     @Override
getExternalMediaDirs()2122     public File[] getExternalMediaDirs() {
2123         // pass
2124         return new File[0];
2125     }
2126 
setScrollYPos(@onNull View view, int scrollPos)2127     public void setScrollYPos(@NonNull View view, int scrollPos) {
2128         mScrollYPos.put(view, scrollPos);
2129     }
2130 
getScrollYPos(@onNull View view)2131     public int getScrollYPos(@NonNull View view) {
2132         Integer pos = mScrollYPos.get(view);
2133         return pos != null ? pos : 0;
2134     }
2135 
setScrollXPos(@onNull View view, int scrollPos)2136     public void setScrollXPos(@NonNull View view, int scrollPos) {
2137         mScrollXPos.put(view, scrollPos);
2138     }
2139 
getScrollXPos(@onNull View view)2140     public int getScrollXPos(@NonNull View view) {
2141         Integer pos = mScrollXPos.get(view);
2142         return pos != null ? pos : 0;
2143     }
2144 
2145     @Override
createDeviceProtectedStorageContext()2146     public Context createDeviceProtectedStorageContext() {
2147         // pass
2148         return null;
2149     }
2150 
2151     @Override
createCredentialProtectedStorageContext()2152     public Context createCredentialProtectedStorageContext() {
2153         // pass
2154         return null;
2155     }
2156 
2157     @Override
isDeviceProtectedStorage()2158     public boolean isDeviceProtectedStorage() {
2159         return false;
2160     }
2161 
2162     @Override
isCredentialProtectedStorage()2163     public boolean isCredentialProtectedStorage() {
2164         return false;
2165     }
2166 
2167     @Override
canLoadUnsafeResources()2168     public boolean canLoadUnsafeResources() {
2169         return true;
2170     }
2171 
2172     @Override
isUiContext()2173     public boolean isUiContext() {
2174         return true;
2175     }
2176 
putUserData(@onNull Key<T> key, @Nullable T data)2177     public <T> void putUserData(@NonNull Key<T> key, @Nullable T data) {
2178         mUserData.put(key, data);
2179     }
2180 
2181     @SuppressWarnings("unchecked")
2182     @Nullable
getUserData(@onNull Key<T> key)2183     public <T> T getUserData(@NonNull Key<T> key) {
2184         return (T) mUserData.get(key);
2185     }
2186 
2187     /** Logs an error message to the error log of the host application. */
error(@onNull String message, @NonNull String... details)2188     public void error(@NonNull String message, @NonNull String... details) {
2189         mLayoutlibCallback.error(message, details);
2190     }
2191 
2192     /** Logs an error message to the error log of the host application. */
error(@onNull String message, @Nullable Throwable t)2193     public void error(@NonNull String message, @Nullable Throwable t) {
2194         mLayoutlibCallback.error(message, t);
2195     }
2196 
2197     /** Logs an error message to the error log of the host application. */
error(@onNull Throwable t)2198     public void error(@NonNull Throwable t) {
2199         mLayoutlibCallback.error(t);
2200     }
2201 
2202     /** Logs a warning to the log of the host application. */
warn(@onNull String message, @Nullable Throwable t)2203     public void warn(@NonNull String message, @Nullable Throwable t) {
2204         mLayoutlibCallback.warn(message, t);
2205     }
2206 
2207     /** Logs a warning to the log of the host application. */
warn(@onNull Throwable t)2208     public void warn(@NonNull Throwable t) {
2209         mLayoutlibCallback.warn(t);
2210     }
2211 
2212     /**
2213      * No two Key instances are considered equal.
2214      *
2215      * @param <T> the type of values associated with the key
2216      */
2217     public static final class Key<T> {
2218         private final String name;
2219 
2220         @NonNull
create(@onNull String name)2221         public static <T> Key<T> create(@NonNull String name) {
2222             return new Key<T>(name);
2223         }
2224 
Key(@onNull String name)2225         private Key(@NonNull String name) {
2226             this.name = name;
2227         }
2228 
2229         /** For debugging only. */
2230         @Override
toString()2231         public String toString() {
2232             return name;
2233         }
2234     }
2235 
2236     private class AttributeHolder {
2237         private final int resourceId;
2238         @NonNull private final ResourceReference reference;
2239 
AttributeHolder(int resourceId, @NonNull ResourceReference reference)2240         private AttributeHolder(int resourceId, @NonNull ResourceReference reference) {
2241             this.resourceId = resourceId;
2242             this.reference = reference;
2243         }
2244 
2245         @NonNull
asReference()2246         private ResourceReference asReference() {
2247             return reference;
2248         }
2249 
getResourceId()2250         private int getResourceId() {
2251             return resourceId;
2252         }
2253 
2254         @NonNull
getName()2255         private String getName() {
2256             return reference.getName();
2257         }
2258 
2259         @NonNull
getNamespace()2260         private ResourceNamespace getNamespace() {
2261             return reference.getNamespace();
2262         }
2263     }
2264 
2265     /**
2266      * The cached value depends on
2267      * <ol>
2268      * <li>{@code int[]}: the attributes for which TypedArray is created </li>
2269      * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
2270      * creation of the TypedArray</li>
2271      * <li>{@code Integer}: the default style used at the time of creation</li>
2272      * </ol>
2273      *
2274      * The class is created by using nested maps resolving one dependency at a time.
2275      * <p/>
2276      * The final value of the nested maps is a pair of the typed array and a map of properties
2277      * that should be added to {@link #mDefaultPropMaps}, if needed.
2278      */
2279     private static class TypedArrayCache {
2280 
2281         private Map<int[],
2282                 Map<List<StyleResourceValue>,
2283                         Map<Integer, Pair<BridgeTypedArray,
2284                                 Map<ResourceReference, ResourceValue>>>>> mCache;
2285 
TypedArrayCache()2286         private TypedArrayCache() {
2287             mCache = new IdentityHashMap<>();
2288         }
2289 
get(int[] attrs, List<StyleResourceValue> themes, int resId)2290         public Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> get(int[] attrs,
2291                 List<StyleResourceValue> themes, int resId) {
2292             Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference,
2293                     ResourceValue>>>>
2294                     cacheFromThemes = mCache.get(attrs);
2295             if (cacheFromThemes != null) {
2296                 Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>>> cacheFromResId =
2297                         cacheFromThemes.get(themes);
2298                 if (cacheFromResId != null) {
2299                     return cacheFromResId.get(resId);
2300                 }
2301             }
2302             return null;
2303         }
2304 
put(int[] attrs, List<StyleResourceValue> themes, int resId, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> value)2305         public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
2306                 Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> value) {
2307             Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference,
2308                     ResourceValue>>>>
2309                     cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>());
2310             Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>>> cacheFromResId =
2311                     cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>());
2312             cacheFromResId.put(resId, value);
2313         }
2314 
2315     }
2316 
2317     @NotNull
getSessionInteractiveData()2318     public SessionInteractiveData getSessionInteractiveData() {
2319         return mSessionInteractiveData;
2320     }
2321 
useThemedIcon()2322     public boolean useThemedIcon() {
2323         return mUseThemedIcon && mRenderResources.hasDynamicColors();
2324     }
2325 
setUseThemedIcon(boolean useThemedIcon)2326     public void setUseThemedIcon(boolean useThemedIcon) {
2327         mUseThemedIcon = useThemedIcon;
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