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