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