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