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