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