BridgeContext.java revision 2bc2daa74eef01135f717eadfab87538a9bef29f
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 17package com.android.layoutlib.bridge.android; 18 19import android.os.IBinder; 20import com.android.annotations.Nullable; 21import com.android.ide.common.rendering.api.AssetRepository; 22import com.android.ide.common.rendering.api.ILayoutPullParser; 23import com.android.ide.common.rendering.api.LayoutLog; 24import com.android.ide.common.rendering.api.LayoutlibCallback; 25import com.android.ide.common.rendering.api.RenderResources; 26import com.android.ide.common.rendering.api.ResourceReference; 27import com.android.ide.common.rendering.api.ResourceValue; 28import com.android.ide.common.rendering.api.StyleResourceValue; 29import com.android.layoutlib.bridge.Bridge; 30import com.android.layoutlib.bridge.BridgeConstants; 31import com.android.layoutlib.bridge.android.view.WindowManagerImpl; 32import com.android.layoutlib.bridge.impl.ParserFactory; 33import com.android.layoutlib.bridge.impl.Stack; 34import com.android.resources.ResourceType; 35import com.android.util.Pair; 36 37import org.xmlpull.v1.XmlPullParser; 38import org.xmlpull.v1.XmlPullParserException; 39 40import android.content.BroadcastReceiver; 41import android.content.ComponentName; 42import android.content.ContentResolver; 43import android.content.Context; 44import android.content.ContextWrapper; 45import android.content.Intent; 46import android.content.IntentFilter; 47import android.content.IntentSender; 48import android.content.ServiceConnection; 49import android.content.SharedPreferences; 50import android.content.pm.ApplicationInfo; 51import android.content.pm.PackageManager; 52import android.content.res.AssetManager; 53import android.content.res.BridgeAssetManager; 54import android.content.res.BridgeResources; 55import android.content.res.BridgeTypedArray; 56import android.content.res.Configuration; 57import android.content.res.Resources; 58import android.content.res.Resources.Theme; 59import android.database.DatabaseErrorHandler; 60import android.database.sqlite.SQLiteDatabase; 61import android.database.sqlite.SQLiteDatabase.CursorFactory; 62import android.graphics.Bitmap; 63import android.graphics.drawable.Drawable; 64import android.hardware.display.DisplayManager; 65import android.net.Uri; 66import android.os.Bundle; 67import android.os.Handler; 68import android.os.Looper; 69import android.os.PowerManager; 70import android.os.UserHandle; 71import android.util.AttributeSet; 72import android.util.DisplayMetrics; 73import android.util.TypedValue; 74import android.view.BridgeInflater; 75import android.view.Display; 76import android.view.DisplayAdjustments; 77import android.view.View; 78import android.view.ViewGroup; 79import android.view.WindowManager; 80import android.view.accessibility.AccessibilityManager; 81import android.view.textservice.TextServicesManager; 82 83import java.io.File; 84import java.io.FileInputStream; 85import java.io.FileNotFoundException; 86import java.io.FileOutputStream; 87import java.io.IOException; 88import java.io.InputStream; 89import java.util.ArrayList; 90import java.util.HashMap; 91import java.util.IdentityHashMap; 92import java.util.List; 93import java.util.Map; 94 95import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; 96 97/** 98 * Custom implementation of Context/Activity to handle non compiled resources. 99 */ 100@SuppressWarnings("deprecation") // For use of Pair. 101public final class BridgeContext extends Context { 102 103 /** The map adds cookies to each view so that IDE can link xml tags to views. */ 104 private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>(); 105 /** 106 * In some cases, when inflating an xml, some objects are created. Then later, the objects are 107 * converted to views. This map stores the mapping from objects to cookies which can then be 108 * used to populate the mViewKeyMap. 109 */ 110 private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>(); 111 private final BridgeAssetManager mAssets; 112 private Resources mSystemResources; 113 private final Object mProjectKey; 114 private final DisplayMetrics mMetrics; 115 private final RenderResources mRenderResources; 116 private final Configuration mConfig; 117 private final ApplicationInfo mApplicationInfo; 118 private final LayoutlibCallback mLayoutlibCallback; 119 private final WindowManager mWindowManager; 120 private final DisplayManager mDisplayManager; 121 122 private Resources.Theme mTheme; 123 124 private final Map<Object, Map<String, String>> mDefaultPropMaps = 125 new IdentityHashMap<Object, Map<String,String>>(); 126 127 // maps for dynamically generated id representing style objects (StyleResourceValue) 128 private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; 129 private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; 130 private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace 131 132 // cache for TypedArray generated from IStyleResourceValue object 133 private Map<int[], Map<Integer, BridgeTypedArray>> mTypedArrayCache; 134 private BridgeInflater mBridgeInflater; 135 136 private BridgeContentResolver mContentResolver; 137 138 private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); 139 private SharedPreferences mSharedPreferences; 140 141 /** 142 * @param projectKey An Object identifying the project. This is used for the cache mechanism. 143 * @param metrics the {@link DisplayMetrics}. 144 * @param renderResources the configured resources (both framework and projects) for this 145 * render. 146 * @param config the Configuration object for this render. 147 * @param targetSdkVersion the targetSdkVersion of the application. 148 */ 149 public BridgeContext(Object projectKey, DisplayMetrics metrics, 150 RenderResources renderResources, 151 AssetRepository assets, 152 LayoutlibCallback layoutlibCallback, 153 Configuration config, 154 int targetSdkVersion, 155 boolean hasRtlSupport) { 156 mProjectKey = projectKey; 157 mMetrics = metrics; 158 mLayoutlibCallback = layoutlibCallback; 159 160 mRenderResources = renderResources; 161 mConfig = config; 162 mAssets = new BridgeAssetManager(); 163 mAssets.setAssetRepository(assets); 164 165 mApplicationInfo = new ApplicationInfo(); 166 mApplicationInfo.targetSdkVersion = targetSdkVersion; 167 if (hasRtlSupport) { 168 mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL; 169 } 170 171 mWindowManager = new WindowManagerImpl(mMetrics); 172 mDisplayManager = new DisplayManager(this); 173 } 174 175 /** 176 * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its 177 * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}. 178 * 179 * @see #disposeResources() 180 */ 181 public void initResources() { 182 AssetManager assetManager = AssetManager.getSystem(); 183 184 mSystemResources = BridgeResources.initSystem( 185 this, 186 assetManager, 187 mMetrics, 188 mConfig, 189 mLayoutlibCallback); 190 mTheme = mSystemResources.newTheme(); 191 } 192 193 /** 194 * Disposes the {@link Resources} singleton. 195 */ 196 public void disposeResources() { 197 BridgeResources.disposeSystem(); 198 } 199 200 public void setBridgeInflater(BridgeInflater inflater) { 201 mBridgeInflater = inflater; 202 } 203 204 public void addViewKey(View view, Object viewKey) { 205 mViewKeyMap.put(view, viewKey); 206 } 207 208 public Object getViewKey(View view) { 209 return mViewKeyMap.get(view); 210 } 211 212 public void addCookie(Object o, Object cookie) { 213 mViewKeyHelpMap.put(o, cookie); 214 } 215 216 public Object getCookie(Object o) { 217 return mViewKeyHelpMap.get(o); 218 } 219 220 public Object getProjectKey() { 221 return mProjectKey; 222 } 223 224 public DisplayMetrics getMetrics() { 225 return mMetrics; 226 } 227 228 public LayoutlibCallback getLayoutlibCallback() { 229 return mLayoutlibCallback; 230 } 231 232 public RenderResources getRenderResources() { 233 return mRenderResources; 234 } 235 236 public Map<String, String> getDefaultPropMap(Object key) { 237 return mDefaultPropMaps.get(key); 238 } 239 240 public Configuration getConfiguration() { 241 return mConfig; 242 } 243 244 /** 245 * Adds a parser to the stack. 246 * @param parser the parser to add. 247 */ 248 public void pushParser(BridgeXmlBlockParser parser) { 249 if (ParserFactory.LOG_PARSER) { 250 System.out.println("PUSH " + parser.getParser().toString()); 251 } 252 mParserStack.push(parser); 253 } 254 255 /** 256 * Removes the parser at the top of the stack 257 */ 258 public void popParser() { 259 BridgeXmlBlockParser parser = mParserStack.pop(); 260 if (ParserFactory.LOG_PARSER) { 261 System.out.println("POPD " + parser.getParser().toString()); 262 } 263 } 264 265 /** 266 * Returns the current parser at the top the of the stack. 267 * @return a parser or null. 268 */ 269 public BridgeXmlBlockParser getCurrentParser() { 270 return mParserStack.peek(); 271 } 272 273 /** 274 * Returns the previous parser. 275 * @return a parser or null if there isn't any previous parser 276 */ 277 public BridgeXmlBlockParser getPreviousParser() { 278 if (mParserStack.size() < 2) { 279 return null; 280 } 281 return mParserStack.get(mParserStack.size() - 2); 282 } 283 284 public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { 285 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); 286 boolean isFrameworkRes = true; 287 if (resourceInfo == null) { 288 resourceInfo = mLayoutlibCallback.resolveResourceId(resid); 289 isFrameworkRes = false; 290 } 291 292 if (resourceInfo == null) { 293 return false; 294 } 295 296 ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), 297 isFrameworkRes); 298 if (resolveRefs) { 299 value = mRenderResources.resolveResValue(value); 300 } 301 302 if (value == null) { 303 // unable to find the attribute. 304 return false; 305 } 306 307 // check if this is a style resource 308 if (value instanceof StyleResourceValue) { 309 // get the id that will represent this style. 310 outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value); 311 return true; 312 } 313 314 int a; 315 // if this is a framework value. 316 if (value.isFramework()) { 317 // look for idName in the android R classes. 318 // use 0 a default res value as it's not a valid id value. 319 a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 320 } else { 321 // look for idName in the project R class. 322 // use 0 a default res value as it's not a valid id value. 323 a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 324 } 325 326 if (a != 0) { 327 outValue.resourceId = a; 328 return true; 329 } 330 331 return false; 332 } 333 334 335 public ResourceReference resolveId(int id) { 336 // first get the String related to this id in the framework 337 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); 338 339 if (resourceInfo != null) { 340 return new ResourceReference(resourceInfo.getSecond(), true); 341 } 342 343 // didn't find a match in the framework? look in the project. 344 if (mLayoutlibCallback != null) { 345 resourceInfo = mLayoutlibCallback.resolveResourceId(id); 346 347 if (resourceInfo != null) { 348 return new ResourceReference(resourceInfo.getSecond(), false); 349 } 350 } 351 352 // The base value for R.style is 0x01030000 and the custom style is 0x02030000. 353 // So, if the second byte is 03, it's probably a style. 354 if ((id >> 16 & 0xFF) == 0x03) { 355 return getStyleByDynamicId(id); 356 } 357 return null; 358 } 359 360 public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, 361 boolean attachToRoot, boolean skipCallbackParser) { 362 boolean isPlatformLayout = resource.isFramework(); 363 364 if (!isPlatformLayout && !skipCallbackParser) { 365 // check if the project callback can provide us with a custom parser. 366 ILayoutPullParser parser = getParser(resource); 367 368 if (parser != null) { 369 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 370 this, resource.isFramework()); 371 try { 372 pushParser(blockParser); 373 return Pair.of( 374 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 375 true); 376 } finally { 377 popParser(); 378 } 379 } 380 } 381 382 ResourceValue resValue; 383 if (resource instanceof ResourceValue) { 384 resValue = (ResourceValue) resource; 385 } else { 386 if (isPlatformLayout) { 387 resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT, 388 resource.getName()); 389 } else { 390 resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT, 391 resource.getName()); 392 } 393 } 394 395 if (resValue != null) { 396 397 File xml = new File(resValue.getValue()); 398 if (xml.isFile()) { 399 // we need to create a pull parser around the layout XML file, and then 400 // give that to our XmlBlockParser 401 try { 402 XmlPullParser parser = ParserFactory.create(xml); 403 404 // set the resource ref to have correct view cookies 405 mBridgeInflater.setResourceReference(resource); 406 407 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 408 this, resource.isFramework()); 409 try { 410 pushParser(blockParser); 411 return Pair.of( 412 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 413 false); 414 } finally { 415 popParser(); 416 } 417 } catch (XmlPullParserException e) { 418 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 419 "Failed to configure parser for " + xml, e, null /*data*/); 420 // we'll return null below. 421 } catch (FileNotFoundException e) { 422 // this shouldn't happen since we check above. 423 } finally { 424 mBridgeInflater.setResourceReference(null); 425 } 426 } else { 427 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 428 String.format("File %s is missing!", xml), null); 429 } 430 } else { 431 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 432 String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", 433 resource.getName()), null); 434 } 435 436 return Pair.of(null, false); 437 } 438 439 @SuppressWarnings("deprecation") 440 private ILayoutPullParser getParser(ResourceReference resource) { 441 ILayoutPullParser parser; 442 if (resource instanceof ResourceValue) { 443 parser = mLayoutlibCallback.getParser((ResourceValue) resource); 444 } else { 445 parser = mLayoutlibCallback.getParser(resource.getName()); 446 } 447 return parser; 448 } 449 450 // ------------ Context methods 451 452 @Override 453 public Resources getResources() { 454 return mSystemResources; 455 } 456 457 @Override 458 public Theme getTheme() { 459 return mTheme; 460 } 461 462 @Override 463 public ClassLoader getClassLoader() { 464 return this.getClass().getClassLoader(); 465 } 466 467 @Override 468 public Object getSystemService(String service) { 469 if (LAYOUT_INFLATER_SERVICE.equals(service)) { 470 return mBridgeInflater; 471 } 472 473 if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) { 474 // we need to return a valid service to avoid NPE 475 return TextServicesManager.getInstance(); 476 } 477 478 if (WINDOW_SERVICE.equals(service)) { 479 return mWindowManager; 480 } 481 482 // needed by SearchView 483 if (INPUT_METHOD_SERVICE.equals(service)) { 484 return null; 485 } 486 487 if (POWER_SERVICE.equals(service)) { 488 return new PowerManager(this, new BridgePowerManager(), new Handler()); 489 } 490 491 if (DISPLAY_SERVICE.equals(service)) { 492 return mDisplayManager; 493 } 494 495 if (ACCESSIBILITY_SERVICE.equals(service)) { 496 return AccessibilityManager.getInstance(this); 497 } 498 499 throw new UnsupportedOperationException("Unsupported Service: " + service); 500 } 501 502 503 @Override 504 public final BridgeTypedArray obtainStyledAttributes(int[] attrs) { 505 // No style is specified here, so create the typed array based on the default theme 506 // and the styles already applied to it. A null value of style indicates that the default 507 // theme should be used. 508 return createStyleBasedTypedArray(null, attrs); 509 } 510 511 @Override 512 public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs) 513 throws Resources.NotFoundException { 514 StyleResourceValue style = null; 515 // get the StyleResourceValue based on the resId; 516 if (resid != 0) { 517 style = getStyleByDynamicId(resid); 518 519 if (style == null) { 520 // In some cases, style may not be a dynamic id, so we do a full search. 521 ResourceReference ref = resolveId(resid); 522 if (ref != null) { 523 style = mRenderResources.getStyle(ref.getName(), ref.isFramework()); 524 } 525 } 526 527 if (style == null) { 528 throw new Resources.NotFoundException(); 529 } 530 } 531 532 if (mTypedArrayCache == null) { 533 mTypedArrayCache = new HashMap<int[], Map<Integer,BridgeTypedArray>>(); 534 535 Map<Integer, BridgeTypedArray> map = new HashMap<Integer, BridgeTypedArray>(); 536 mTypedArrayCache.put(attrs, map); 537 538 BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs); 539 map.put(resid, ta); 540 541 return ta; 542 } 543 544 // get the 2nd map 545 Map<Integer, BridgeTypedArray> map = mTypedArrayCache.get(attrs); 546 if (map == null) { 547 map = new HashMap<Integer, BridgeTypedArray>(); 548 mTypedArrayCache.put(attrs, map); 549 } 550 551 // get the array from the 2nd map 552 BridgeTypedArray ta = map.get(resid); 553 554 if (ta == null) { 555 ta = createStyleBasedTypedArray(style, attrs); 556 map.put(resid, ta); 557 } 558 559 return ta; 560 } 561 562 @Override 563 public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { 564 return obtainStyledAttributes(set, attrs, 0, 0); 565 } 566 567 @Override 568 public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, 569 int defStyleAttr, int defStyleRes) { 570 571 Map<String, String> defaultPropMap = null; 572 boolean isPlatformFile = true; 573 574 // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java 575 if (set instanceof BridgeXmlBlockParser) { 576 BridgeXmlBlockParser parser; 577 parser = (BridgeXmlBlockParser)set; 578 579 isPlatformFile = parser.isPlatformFile(); 580 581 Object key = parser.getViewCookie(); 582 if (key != null) { 583 defaultPropMap = mDefaultPropMaps.get(key); 584 if (defaultPropMap == null) { 585 defaultPropMap = new HashMap<String, String>(); 586 mDefaultPropMaps.put(key, defaultPropMap); 587 } 588 } 589 590 } else if (set instanceof BridgeLayoutParamsMapAttributes) { 591 // this is only for temp layout params generated dynamically, so this is never 592 // platform content. 593 isPlatformFile = false; 594 } else if (set != null) { // null parser is ok 595 // really this should not be happening since its instantiated in Bridge 596 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 597 "Parser is not a BridgeXmlBlockParser!", null); 598 return null; 599 } 600 601 List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); 602 603 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 604 isPlatformFile); 605 606 // look for a custom style. 607 String customStyle = null; 608 if (set != null) { 609 customStyle = set.getAttributeValue(null, "style"); 610 } 611 612 StyleResourceValue customStyleValues = null; 613 if (customStyle != null) { 614 ResourceValue item = mRenderResources.findResValue(customStyle, 615 isPlatformFile /*forceFrameworkOnly*/); 616 617 // resolve it in case it links to something else 618 item = mRenderResources.resolveResValue(item); 619 620 if (item instanceof StyleResourceValue) { 621 customStyleValues = (StyleResourceValue)item; 622 } 623 } 624 625 // resolve the defStyleAttr value into a IStyleResourceValue 626 StyleResourceValue defStyleValues = null; 627 628 if (defStyleAttr != 0) { 629 // get the name from the int. 630 Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); 631 632 if (defStyleAttribute == null) { 633 // This should be rare. Happens trying to map R.style.foo to @style/foo fails. 634 // This will happen if the user explicitly used a non existing int value for 635 // defStyleAttr or there's something wrong with the project structure/build. 636 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, 637 "Failed to find the style corresponding to the id " + defStyleAttr, null); 638 } else { 639 if (defaultPropMap != null) { 640 String defStyleName = defStyleAttribute.getFirst(); 641 if (defStyleAttribute.getSecond()) { 642 defStyleName = "android:" + defStyleName; 643 } 644 defaultPropMap.put("style", defStyleName); 645 } 646 647 // look for the style in the current theme, and its parent: 648 ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(), 649 defStyleAttribute.getSecond()); 650 651 if (item != null) { 652 // item is a reference to a style entry. Search for it. 653 item = mRenderResources.findResValue(item.getValue(), item.isFramework()); 654 655 if (item instanceof StyleResourceValue) { 656 defStyleValues = (StyleResourceValue) item; 657 } 658 } else { 659 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 660 String.format( 661 "Failed to find style '%s' in current theme", 662 defStyleAttribute.getFirst()), 663 null); 664 } 665 } 666 } else if (defStyleRes != 0) { 667 boolean isFrameworkRes = true; 668 Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); 669 if (value == null) { 670 value = mLayoutlibCallback.resolveResourceId(defStyleRes); 671 isFrameworkRes = false; 672 } 673 674 if (value != null) { 675 if ((value.getFirst() == ResourceType.STYLE)) { 676 // look for the style in all resources: 677 StyleResourceValue item = mRenderResources.getStyle(value.getSecond(), 678 isFrameworkRes); 679 if (item != null) { 680 if (defaultPropMap != null) { 681 defaultPropMap.put("style", item.getName()); 682 } 683 684 defStyleValues = item; 685 } else { 686 Bridge.getLog().error(null, 687 String.format( 688 "Style with id 0x%x (resolved to '%s') does not exist.", 689 defStyleRes, value.getSecond()), 690 null); 691 } 692 } else { 693 Bridge.getLog().error(null, 694 String.format( 695 "Resource id 0x%x is not of type STYLE (instead %s)", 696 defStyleRes, value.getFirst().toString()), 697 null); 698 } 699 } else { 700 Bridge.getLog().error(null, 701 String.format( 702 "Failed to find style with id 0x%x in current theme", 703 defStyleRes), 704 null); 705 } 706 } 707 708 String appNamespace = mLayoutlibCallback.getNamespace(); 709 710 if (attributeList != null) { 711 for (int index = 0 ; index < attributeList.size() ; index++) { 712 Pair<String, Boolean> attribute = attributeList.get(index); 713 714 if (attribute == null) { 715 continue; 716 } 717 718 String attrName = attribute.getFirst(); 719 boolean frameworkAttr = attribute.getSecond(); 720 String value = null; 721 if (set != null) { 722 value = set.getAttributeValue( 723 frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, 724 attrName); 725 726 // if this is an app attribute, and the first get fails, try with the 727 // new res-auto namespace as well 728 if (!frameworkAttr && value == null) { 729 value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); 730 } 731 } 732 733 // if there's no direct value for this attribute in the XML, we look for default 734 // values in the widget defStyle, and then in the theme. 735 if (value == null) { 736 ResourceValue resValue = null; 737 738 // look for the value in the custom style first (and its parent if needed) 739 if (customStyleValues != null) { 740 resValue = mRenderResources.findItemInStyle(customStyleValues, 741 attrName, frameworkAttr); 742 } 743 744 // then look for the value in the default Style (and its parent if needed) 745 if (resValue == null && defStyleValues != null) { 746 resValue = mRenderResources.findItemInStyle(defStyleValues, 747 attrName, frameworkAttr); 748 } 749 750 // if the item is not present in the defStyle, we look in the main theme (and 751 // its parent themes) 752 if (resValue == null) { 753 resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); 754 } 755 756 // if we found a value, we make sure this doesn't reference another value. 757 // So we resolve it. 758 if (resValue != null) { 759 // put the first default value, before the resolution. 760 if (defaultPropMap != null) { 761 defaultPropMap.put(attrName, resValue.getValue()); 762 } 763 764 resValue = mRenderResources.resolveResValue(resValue); 765 } 766 767 ta.bridgeSetValue(index, attrName, frameworkAttr, resValue); 768 } else { 769 // there is a value in the XML, but we need to resolve it in case it's 770 // referencing another resource or a theme value. 771 ta.bridgeSetValue(index, attrName, frameworkAttr, 772 mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); 773 } 774 } 775 } 776 777 ta.sealArray(); 778 779 return ta; 780 } 781 782 @Override 783 public Looper getMainLooper() { 784 return Looper.myLooper(); 785 } 786 787 788 @Override 789 public String getPackageName() { 790 if (mApplicationInfo.packageName == null) { 791 mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE); 792 } 793 return mApplicationInfo.packageName; 794 } 795 796 // ------------- private new methods 797 798 /** 799 * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the 800 * values found in the given style. If no style is specified, the default theme, along with the 801 * styles applied to it are used. 802 * 803 * @see #obtainStyledAttributes(int, int[]) 804 */ 805 private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style, 806 int[] attrs) throws Resources.NotFoundException { 807 808 List<Pair<String, Boolean>> attributes = searchAttrs(attrs); 809 810 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 811 false); 812 813 // for each attribute, get its name so that we can search it in the style 814 for (int i = 0 ; i < attrs.length ; i++) { 815 Pair<String, Boolean> attribute = attributes.get(i); 816 817 if (attribute != null) { 818 // look for the value in the given style 819 ResourceValue resValue; 820 if (style != null) { 821 resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(), 822 attribute.getSecond()); 823 } else { 824 resValue = mRenderResources.findItemInTheme(attribute.getFirst(), 825 attribute.getSecond()); 826 } 827 828 if (resValue != null) { 829 // resolve it to make sure there are no references left. 830 ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), 831 mRenderResources.resolveResValue(resValue)); 832 } 833 } 834 } 835 836 ta.sealArray(); 837 838 return ta; 839 } 840 841 /** 842 * The input int[] attrs is a list of attributes. The returns a list of information about 843 * each attributes. The information is (name, isFramework) 844 * <p/> 845 * 846 * @param attrs An attribute array reference given to obtainStyledAttributes. 847 * @return List of attribute information. 848 */ 849 private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { 850 List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); 851 852 // for each attribute, get its name so that we can search it in the style 853 for (int attr : attrs) { 854 Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr); 855 boolean isFramework = false; 856 if (resolvedResource != null) { 857 isFramework = true; 858 } else { 859 resolvedResource = mLayoutlibCallback.resolveResourceId(attr); 860 } 861 862 if (resolvedResource != null) { 863 results.add(Pair.of(resolvedResource.getSecond(), isFramework)); 864 } else { 865 results.add(null); 866 } 867 } 868 869 return results; 870 } 871 872 /** 873 * Searches for the attribute referenced by its internal id. 874 * 875 * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. 876 * @return A (name, isFramework) pair describing the attribute if found. Returns null 877 * if nothing is found. 878 */ 879 public Pair<String, Boolean> searchAttr(int attr) { 880 Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); 881 if (info != null) { 882 return Pair.of(info.getSecond(), Boolean.TRUE); 883 } 884 885 info = mLayoutlibCallback.resolveResourceId(attr); 886 if (info != null) { 887 return Pair.of(info.getSecond(), Boolean.FALSE); 888 } 889 890 return null; 891 } 892 893 public int getDynamicIdByStyle(StyleResourceValue resValue) { 894 if (mDynamicIdToStyleMap == null) { 895 // create the maps. 896 mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>(); 897 mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>(); 898 } 899 900 // look for an existing id 901 Integer id = mStyleToDynamicIdMap.get(resValue); 902 903 if (id == null) { 904 // generate a new id 905 id = ++mDynamicIdGenerator; 906 907 // and add it to the maps. 908 mDynamicIdToStyleMap.put(id, resValue); 909 mStyleToDynamicIdMap.put(resValue, id); 910 } 911 912 return id; 913 } 914 915 private StyleResourceValue getStyleByDynamicId(int i) { 916 if (mDynamicIdToStyleMap != null) { 917 return mDynamicIdToStyleMap.get(i); 918 } 919 920 return null; 921 } 922 923 public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) { 924 if (getRenderResources().getFrameworkResource(resType, resName) != null) { 925 // Bridge.getResourceId creates a new resource id if an existing one isn't found. So, 926 // we check for the existence of the resource before calling it. 927 return Bridge.getResourceId(resType, resName); 928 } 929 930 return defValue; 931 } 932 933 public int getProjectResourceValue(ResourceType resType, String resName, int defValue) { 934 // getResourceId creates a new resource id if an existing resource id isn't found. So, we 935 // check for the existence of the resource before calling it. 936 if (getRenderResources().getProjectResource(resType, resName) != null) { 937 if (mLayoutlibCallback != null) { 938 Integer value = mLayoutlibCallback.getResourceId(resType, resName); 939 if (value != null) { 940 return value; 941 } 942 } 943 } 944 945 return defValue; 946 } 947 948 public static Context getBaseContext(Context context) { 949 while (context instanceof ContextWrapper) { 950 context = ((ContextWrapper) context).getBaseContext(); 951 } 952 return context; 953 } 954 955 //------------ NOT OVERRIDEN -------------------- 956 957 @Override 958 public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { 959 // pass 960 return false; 961 } 962 963 @Override 964 public int checkCallingOrSelfPermission(String arg0) { 965 // pass 966 return 0; 967 } 968 969 @Override 970 public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { 971 // pass 972 return 0; 973 } 974 975 @Override 976 public int checkCallingPermission(String arg0) { 977 // pass 978 return 0; 979 } 980 981 @Override 982 public int checkCallingUriPermission(Uri arg0, int arg1) { 983 // pass 984 return 0; 985 } 986 987 @Override 988 public int checkPermission(String arg0, int arg1, int arg2) { 989 // pass 990 return 0; 991 } 992 993 @Override 994 public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) { 995 // pass 996 return 0; 997 } 998 999 @Override 1000 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { 1001 // pass 1002 return 0; 1003 } 1004 1005 @Override 1006 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) { 1007 // pass 1008 return 0; 1009 } 1010 1011 @Override 1012 public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, 1013 int arg4, int arg5) { 1014 // pass 1015 return 0; 1016 } 1017 1018 @Override 1019 public void clearWallpaper() { 1020 // pass 1021 1022 } 1023 1024 @Override 1025 public Context createPackageContext(String arg0, int arg1) { 1026 // pass 1027 return null; 1028 } 1029 1030 @Override 1031 public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { 1032 // pass 1033 return null; 1034 } 1035 1036 @Override 1037 public Context createConfigurationContext(Configuration overrideConfiguration) { 1038 // pass 1039 return null; 1040 } 1041 1042 @Override 1043 public Context createDisplayContext(Display display) { 1044 // pass 1045 return null; 1046 } 1047 1048 @Override 1049 public String[] databaseList() { 1050 // pass 1051 return null; 1052 } 1053 1054 @Override 1055 public Context createApplicationContext(ApplicationInfo application, int flags) 1056 throws PackageManager.NameNotFoundException { 1057 return null; 1058 } 1059 1060 @Override 1061 public boolean deleteDatabase(String arg0) { 1062 // pass 1063 return false; 1064 } 1065 1066 @Override 1067 public boolean deleteFile(String arg0) { 1068 // pass 1069 return false; 1070 } 1071 1072 @Override 1073 public void enforceCallingOrSelfPermission(String arg0, String arg1) { 1074 // pass 1075 1076 } 1077 1078 @Override 1079 public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, 1080 String arg2) { 1081 // pass 1082 1083 } 1084 1085 @Override 1086 public void enforceCallingPermission(String arg0, String arg1) { 1087 // pass 1088 1089 } 1090 1091 @Override 1092 public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { 1093 // pass 1094 1095 } 1096 1097 @Override 1098 public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { 1099 // pass 1100 1101 } 1102 1103 @Override 1104 public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, 1105 String arg4) { 1106 // pass 1107 1108 } 1109 1110 @Override 1111 public void enforceUriPermission(Uri arg0, String arg1, String arg2, 1112 int arg3, int arg4, int arg5, String arg6) { 1113 // pass 1114 1115 } 1116 1117 @Override 1118 public String[] fileList() { 1119 // pass 1120 return null; 1121 } 1122 1123 @Override 1124 public BridgeAssetManager getAssets() { 1125 return mAssets; 1126 } 1127 1128 @Override 1129 public File getCacheDir() { 1130 // pass 1131 return null; 1132 } 1133 1134 @Override 1135 public File getCodeCacheDir() { 1136 // pass 1137 return null; 1138 } 1139 1140 @Override 1141 public File getExternalCacheDir() { 1142 // pass 1143 return null; 1144 } 1145 1146 @Override 1147 public ContentResolver getContentResolver() { 1148 if (mContentResolver == null) { 1149 mContentResolver = new BridgeContentResolver(this); 1150 } 1151 return mContentResolver; 1152 } 1153 1154 @Override 1155 public File getDatabasePath(String arg0) { 1156 // pass 1157 return null; 1158 } 1159 1160 @Override 1161 public File getDir(String arg0, int arg1) { 1162 // pass 1163 return null; 1164 } 1165 1166 @Override 1167 public File getFileStreamPath(String arg0) { 1168 // pass 1169 return null; 1170 } 1171 1172 @Override 1173 public File getFilesDir() { 1174 // pass 1175 return null; 1176 } 1177 1178 @Override 1179 public File getNoBackupFilesDir() { 1180 // pass 1181 return null; 1182 } 1183 1184 @Override 1185 public File getExternalFilesDir(String type) { 1186 // pass 1187 return null; 1188 } 1189 1190 @Override 1191 public String getPackageCodePath() { 1192 // pass 1193 return null; 1194 } 1195 1196 @Override 1197 public PackageManager getPackageManager() { 1198 // pass 1199 return null; 1200 } 1201 1202 @Override 1203 public String getBasePackageName() { 1204 // pass 1205 return null; 1206 } 1207 1208 @Override 1209 public String getOpPackageName() { 1210 // pass 1211 return null; 1212 } 1213 1214 @Override 1215 public ApplicationInfo getApplicationInfo() { 1216 return mApplicationInfo; 1217 } 1218 1219 @Override 1220 public String getPackageResourcePath() { 1221 // pass 1222 return null; 1223 } 1224 1225 @Override 1226 public File getSharedPrefsFile(String name) { 1227 // pass 1228 return null; 1229 } 1230 1231 @Override 1232 public SharedPreferences getSharedPreferences(String arg0, int arg1) { 1233 if (mSharedPreferences == null) { 1234 mSharedPreferences = new BridgeSharedPreferences(); 1235 } 1236 return mSharedPreferences; 1237 } 1238 1239 @Override 1240 public Drawable getWallpaper() { 1241 // pass 1242 return null; 1243 } 1244 1245 @Override 1246 public int getWallpaperDesiredMinimumWidth() { 1247 return -1; 1248 } 1249 1250 @Override 1251 public int getWallpaperDesiredMinimumHeight() { 1252 return -1; 1253 } 1254 1255 @Override 1256 public void grantUriPermission(String arg0, Uri arg1, int arg2) { 1257 // pass 1258 1259 } 1260 1261 @Override 1262 public FileInputStream openFileInput(String arg0) throws FileNotFoundException { 1263 // pass 1264 return null; 1265 } 1266 1267 @Override 1268 public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { 1269 // pass 1270 return null; 1271 } 1272 1273 @Override 1274 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { 1275 // pass 1276 return null; 1277 } 1278 1279 @Override 1280 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, 1281 CursorFactory arg2, DatabaseErrorHandler arg3) { 1282 // pass 1283 return null; 1284 } 1285 1286 @Override 1287 public Drawable peekWallpaper() { 1288 // pass 1289 return null; 1290 } 1291 1292 @Override 1293 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { 1294 // pass 1295 return null; 1296 } 1297 1298 @Override 1299 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1300 String arg2, Handler arg3) { 1301 // pass 1302 return null; 1303 } 1304 1305 @Override 1306 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1307 IntentFilter arg1, String arg2, Handler arg3) { 1308 // pass 1309 return null; 1310 } 1311 1312 @Override 1313 public void removeStickyBroadcast(Intent arg0) { 1314 // pass 1315 1316 } 1317 1318 @Override 1319 public void revokeUriPermission(Uri arg0, int arg1) { 1320 // pass 1321 1322 } 1323 1324 @Override 1325 public void sendBroadcast(Intent arg0) { 1326 // pass 1327 1328 } 1329 1330 @Override 1331 public void sendBroadcast(Intent arg0, String arg1) { 1332 // pass 1333 1334 } 1335 1336 @Override 1337 public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { 1338 // pass 1339 } 1340 1341 @Override 1342 public void sendOrderedBroadcast(Intent arg0, String arg1) { 1343 // pass 1344 1345 } 1346 1347 @Override 1348 public void sendOrderedBroadcast(Intent arg0, String arg1, 1349 BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1350 Bundle arg6) { 1351 // pass 1352 1353 } 1354 1355 @Override 1356 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 1357 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 1358 String initialData, Bundle initialExtras) { 1359 // pass 1360 } 1361 1362 @Override 1363 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1364 // pass 1365 } 1366 1367 @Override 1368 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1369 String receiverPermission) { 1370 // pass 1371 } 1372 1373 @Override 1374 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1375 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 1376 int initialCode, String initialData, Bundle initialExtras) { 1377 // pass 1378 } 1379 1380 @Override 1381 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1382 String receiverPermission, int appOp, BroadcastReceiver resultReceiver, 1383 Handler scheduler, 1384 int initialCode, String initialData, Bundle initialExtras) { 1385 // pass 1386 } 1387 1388 @Override 1389 public void sendStickyBroadcast(Intent arg0) { 1390 // pass 1391 1392 } 1393 1394 @Override 1395 public void sendStickyOrderedBroadcast(Intent intent, 1396 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, 1397 Bundle initialExtras) { 1398 // pass 1399 } 1400 1401 @Override 1402 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 1403 // pass 1404 } 1405 1406 @Override 1407 public void sendStickyOrderedBroadcastAsUser(Intent intent, 1408 UserHandle user, BroadcastReceiver resultReceiver, 1409 Handler scheduler, int initialCode, String initialData, 1410 Bundle initialExtras) { 1411 // pass 1412 } 1413 1414 @Override 1415 public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { 1416 // pass 1417 } 1418 1419 @Override 1420 public void setTheme(int arg0) { 1421 // pass 1422 1423 } 1424 1425 @Override 1426 public void setWallpaper(Bitmap arg0) throws IOException { 1427 // pass 1428 1429 } 1430 1431 @Override 1432 public void setWallpaper(InputStream arg0) throws IOException { 1433 // pass 1434 1435 } 1436 1437 @Override 1438 public void startActivity(Intent arg0) { 1439 // pass 1440 } 1441 1442 @Override 1443 public void startActivity(Intent arg0, Bundle arg1) { 1444 // pass 1445 } 1446 1447 @Override 1448 public void startIntentSender(IntentSender intent, 1449 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 1450 throws IntentSender.SendIntentException { 1451 // pass 1452 } 1453 1454 @Override 1455 public void startIntentSender(IntentSender intent, 1456 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1457 Bundle options) throws IntentSender.SendIntentException { 1458 // pass 1459 } 1460 1461 @Override 1462 public boolean startInstrumentation(ComponentName arg0, String arg1, 1463 Bundle arg2) { 1464 // pass 1465 return false; 1466 } 1467 1468 @Override 1469 public ComponentName startService(Intent arg0) { 1470 // pass 1471 return null; 1472 } 1473 1474 @Override 1475 public boolean stopService(Intent arg0) { 1476 // pass 1477 return false; 1478 } 1479 1480 @Override 1481 public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { 1482 // pass 1483 return null; 1484 } 1485 1486 @Override 1487 public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { 1488 // pass 1489 return false; 1490 } 1491 1492 @Override 1493 public void unbindService(ServiceConnection arg0) { 1494 // pass 1495 1496 } 1497 1498 @Override 1499 public void unregisterReceiver(BroadcastReceiver arg0) { 1500 // pass 1501 1502 } 1503 1504 @Override 1505 public Context getApplicationContext() { 1506 return this; 1507 } 1508 1509 @Override 1510 public void startActivities(Intent[] arg0) { 1511 // pass 1512 1513 } 1514 1515 @Override 1516 public void startActivities(Intent[] arg0, Bundle arg1) { 1517 // pass 1518 1519 } 1520 1521 @Override 1522 public boolean isRestricted() { 1523 return false; 1524 } 1525 1526 @Override 1527 public File getObbDir() { 1528 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null); 1529 return null; 1530 } 1531 1532 @Override 1533 public DisplayAdjustments getDisplayAdjustments(int displayId) { 1534 // pass 1535 return null; 1536 } 1537 1538 @Override 1539 public int getUserId() { 1540 return 0; // not used 1541 } 1542 1543 @Override 1544 public File[] getExternalFilesDirs(String type) { 1545 // pass 1546 return new File[0]; 1547 } 1548 1549 @Override 1550 public File[] getObbDirs() { 1551 // pass 1552 return new File[0]; 1553 } 1554 1555 @Override 1556 public File[] getExternalCacheDirs() { 1557 // pass 1558 return new File[0]; 1559 } 1560 1561 @Override 1562 public File[] getExternalMediaDirs() { 1563 // pass 1564 return new File[0]; 1565 } 1566} 1567