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